IMPALA-4813: Round on divide and multiply

Address rounding on divide and multiply when results are truncated.

Testing: Manually ran some divides that should overflow, then added
the results to the test.  Made the decimal-test use rounding behavior
by default, and now the error margin of the test has decreased.

Initial perf results:

Multiply is totall uninteresting so far, all implementations
return the same values in the same time:

+-------------------------+-----------------------------------+
| sum(l_quantity * l_tax) | sum(l_extendedprice * l_discount) |
+-------------------------+-----------------------------------+
| 61202493.3700           | 114698450836.4234                 |
+-------------------------+-----------------------------------+
Fetched 1 row(s) in 1.13s

Divide shows no regression from prior with DECIMAL_V2 off:

+-----------------------------+-----------------------------------+
| sum(l_quantity / l_tax)     | sum(l_extendedprice / l_discount) |
+-----------------------------+-----------------------------------+
| 46178777464.523809516381723 | 61076151920731.010714279183910    |
+-----------------------------+-----------------------------------+
before:  Fetched 1 row(s) in 13.08s
after:   Fetched 1 row(s) in 13.06s

And with DECIMAL_V2 on:

+-----------------------------+-----------------------------------+
| sum(l_quantity / l_tax)     | sum(l_extendedprice / l_discount) |
+-----------------------------+-----------------------------------+
| 46178777464.523809523847285 | 61076151920731.010714285714202    |
+-----------------------------+-----------------------------------+
Fetched 1 row(s) in 16.06s

So the performance regression is not as bad as expected.  Still,
divide performance could use some work.

Change-Id: Ie6bfcbe37555b74598d409c6f84f06b0ae5c4312
Reviewed-on: http://gerrit.cloudera.org:8080/6132
Reviewed-by: Dan Hecht <[email protected]>
Tested-by: Impala Public Jenkins


Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/c87ab35a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/c87ab35a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/c87ab35a

Branch: refs/heads/master
Commit: c87ab35af18d93b5f5e31b6adc0b20bc1ecf165a
Parents: c463796
Author: Zach Amsden <[email protected]>
Authored: Fri Feb 24 00:55:38 2017 +0000
Committer: Impala Public Jenkins <[email protected]>
Committed: Thu Mar 2 20:12:05 2017 +0000

----------------------------------------------------------------------
 be/src/exprs/aggregate-functions-ir.cc          |   3 +-
 be/src/exprs/decimal-operators-ir.cc            |  18 +-
 be/src/exprs/expr-test.cc                       | 377 +++++++++++-
 be/src/runtime/decimal-test.cc                  | 613 ++++++++++---------
 be/src/runtime/decimal-value.h                  |  81 +--
 be/src/runtime/decimal-value.inline.h           | 107 +++-
 be/src/runtime/types.cc                         |   7 +
 be/src/runtime/types.h                          |  12 +
 be/src/util/bit-util-test.cc                    |  28 +
 be/src/util/bit-util.h                          |  25 +-
 be/src/util/string-parser.h                     |   6 -
 .../queries/QueryTest/decimal-exprs.test        |  16 +-
 12 files changed, 864 insertions(+), 429 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/exprs/aggregate-functions-ir.cc
----------------------------------------------------------------------
diff --git a/be/src/exprs/aggregate-functions-ir.cc 
b/be/src/exprs/aggregate-functions-ir.cc
index 6c8c781..10a775d 100644
--- a/be/src/exprs/aggregate-functions-ir.cc
+++ b/be/src/exprs/aggregate-functions-ir.cc
@@ -447,8 +447,9 @@ DecimalVal 
AggregateFunctions::DecimalAvgGetValue(FunctionContext* ctx,
   int sum_scale = 
ctx->impl()->GetConstFnAttr(FunctionContextImpl::ARG_TYPE_SCALE, 0);
   bool is_nan = false;
   bool overflow = false;
+  bool round = ctx->impl()->GetConstFnAttr(FunctionContextImpl::DECIMAL_V2);
   Decimal16Value result = sum.Divide<int128_t>(sum_scale, count, 0 /* count's 
scale */,
-      output_precision, output_scale, &is_nan, &overflow);
+      output_precision, output_scale, round, &is_nan, &overflow);
   if (UNLIKELY(is_nan)) return DecimalVal::null();
   if (UNLIKELY(overflow)) {
     ctx->AddWarning("Avg computation overflowed, returning NULL");

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/exprs/decimal-operators-ir.cc
----------------------------------------------------------------------
diff --git a/be/src/exprs/decimal-operators-ir.cc 
b/be/src/exprs/decimal-operators-ir.cc
index 6ea48f7..e502dda 100644
--- a/be/src/exprs/decimal-operators-ir.cc
+++ b/be/src/exprs/decimal-operators-ir.cc
@@ -679,20 +679,22 @@ BooleanVal DecimalOperators::CastToBooleanVal(
         
ctx->impl()->GetConstFnAttr(FunctionContextImpl::RETURN_TYPE_PRECISION); \
     int return_scale = \
         ctx->impl()->GetConstFnAttr(FunctionContextImpl::RETURN_TYPE_SCALE); \
+    bool round = \
+        ctx->impl()->GetConstFnAttr(FunctionContextImpl::DECIMAL_V2); \
     switch 
(ctx->impl()->GetConstFnAttr(FunctionContextImpl::RETURN_TYPE_SIZE)) { \
       case 4: { \
         Decimal4Value x_val = GetDecimal4Value(x, x_size, &overflow); \
         Decimal4Value y_val = GetDecimal4Value(y, y_size, &overflow); \
         Decimal4Value result = x_val.OP_FN<int32_t>(x_scale, y_val, y_scale, \
-            return_precision, return_scale, &overflow); \
-        DCHECK(!overflow) << "Cannot overflow except with Decimal17Value"; \
+            return_precision, return_scale, round, &overflow); \
+        DCHECK(!overflow) << "Cannot overflow except with Decimal16Value"; \
         return DecimalVal(result.value()); \
       } \
       case 8: { \
         Decimal8Value x_val = GetDecimal8Value(x, x_size, &overflow); \
         Decimal8Value y_val = GetDecimal8Value(y, y_size, &overflow); \
         Decimal8Value result = x_val.OP_FN<int64_t>(x_scale, y_val, y_scale, \
-            return_precision, return_scale, &overflow); \
+            return_precision, return_scale, round, &overflow); \
         DCHECK(!overflow) << "Cannot overflow except with Decimal16Value"; \
         return DecimalVal(result.value()); \
       } \
@@ -700,7 +702,7 @@ BooleanVal DecimalOperators::CastToBooleanVal(
         Decimal16Value x_val = GetDecimal16Value(x, x_size, &overflow); \
         Decimal16Value y_val = GetDecimal16Value(y, y_size, &overflow); \
         Decimal16Value result = x_val.OP_FN<int128_t>(x_scale, y_val, y_scale, 
\
-            return_precision, return_scale, &overflow); \
+            return_precision, return_scale, round, &overflow); \
         RETURN_IF_OVERFLOW(ctx, overflow, DecimalVal); \
         return DecimalVal(result.value()); \
       } \
@@ -724,12 +726,14 @@ BooleanVal DecimalOperators::CastToBooleanVal(
         
ctx->impl()->GetConstFnAttr(FunctionContextImpl::RETURN_TYPE_PRECISION); \
     int return_scale = \
         ctx->impl()->GetConstFnAttr(FunctionContextImpl::RETURN_TYPE_SCALE); \
+    bool round = \
+        ctx->impl()->GetConstFnAttr(FunctionContextImpl::DECIMAL_V2); \
     switch 
(ctx->impl()->GetConstFnAttr(FunctionContextImpl::RETURN_TYPE_SIZE)) { \
       case 4: { \
         Decimal4Value x_val = GetDecimal4Value(x, x_size, &overflow); \
         Decimal4Value y_val = GetDecimal4Value(y, y_size, &overflow); \
         Decimal4Value result = x_val.OP_FN<int32_t>(x_scale, y_val, y_scale, \
-            return_precision, return_scale, &is_nan, &overflow); \
+            return_precision, return_scale, round, &is_nan, &overflow); \
         DCHECK(!overflow) << "Cannot overflow except with Decimal16Value"; \
         if (is_nan) return DecimalVal::null(); \
         return DecimalVal(result.value()); \
@@ -738,7 +742,7 @@ BooleanVal DecimalOperators::CastToBooleanVal(
         Decimal8Value x_val = GetDecimal8Value(x, x_size, &overflow); \
         Decimal8Value y_val = GetDecimal8Value(y, y_size, &overflow); \
         Decimal8Value result = x_val.OP_FN<int64_t>(x_scale, y_val, y_scale, \
-            return_precision, return_scale, &is_nan, &overflow); \
+            return_precision, return_scale, round, &is_nan, &overflow); \
         DCHECK(!overflow) << "Cannot overflow except with Decimal16Value"; \
         if (is_nan) return DecimalVal::null(); \
         return DecimalVal(result.value()); \
@@ -747,7 +751,7 @@ BooleanVal DecimalOperators::CastToBooleanVal(
         Decimal16Value x_val = GetDecimal16Value(x, x_size, &overflow); \
         Decimal16Value y_val = GetDecimal16Value(y, y_size, &overflow); \
         Decimal16Value result = x_val.OP_FN<int128_t>(x_scale, y_val, y_scale, 
\
-            return_precision, return_scale, &is_nan, &overflow); \
+            return_precision, return_scale, round, &is_nan, &overflow); \
         RETURN_IF_OVERFLOW(ctx, overflow, DecimalVal); \
         if (is_nan) return DecimalVal::null(); \
         return DecimalVal(result.value()); \

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/exprs/expr-test.cc
----------------------------------------------------------------------
diff --git a/be/src/exprs/expr-test.cc b/be/src/exprs/expr-test.cc
index e9dbd76..604644e 100644
--- a/be/src/exprs/expr-test.cc
+++ b/be/src/exprs/expr-test.cc
@@ -1387,23 +1387,380 @@ DecimalTestCase decimal_cases[] = {
        10000000000ll * 10000000000ll * 10000000000ll, 38, 6 }}},
   { "cast(98765432109876543210 as decimal(20,0)) / "
     "cast(98765432109876543211 as decimal(20,0))",
-    {{ false,                  0, 38,  0 },
-     { false, 999999999999999999, 38, 18 }}},
+    {{ false,                   0, 38,  0 },
+     { false, 1000000000000000000, 38, 18 }}},
   { "cast(111111.1111 as decimal(20, 10)) / cast(.7777 as decimal(38, 38))",
     {{ true,             0, 38, 38 },
-     { false, 142871429985, 38,  6 }}},
+     { false, 142871429986, 38,  6 }}},
   { "2.0 / 3.0",
     {{ false,   6666, 6, 4},
-     { false, 666666, 8, 6}}},
+     { false, 666667, 8, 6}}},
   { "-2.0 / 3.0",
     {{ false,   -6666, 6, 4},
-     { false, -666666, 8, 6}}},
+     { false, -666667, 8, 6}}},
   { "2.0 / -3.0",
     {{ false,   -6666, 6, 4},
-     { false, -666666, 8, 6}}},
+     { false, -666667, 8, 6}}},
   { "-2.0 / -3.0",
     {{ false,   6666, 6, 4},
-     { false, 666666, 8, 6}}},
+     { false, 666667, 8, 6}}},
+  // Test divide rounding
+  { "10.10 / 3.0",
+    {{ false, 336666, 8, 5 },
+     { false, 3366667, 9, 6 }}},
+  { "cast(-10.10 as decimal(4,2)) / 3.0", // XXX JIRA: IMPALA-4877
+    {{ false, -336666, 8, 5 },
+     { false, -3366667, 9, 6 }}},
+  { "10.10 / 20.3",
+    {{ false, 497536, 9, 6 },
+     { false, 497537, 9, 6 }}},
+  { "10.10 / -20.3",
+    {{ false, -497536, 9, 6 },
+     { false, -497537, 9, 6 }}},
+  // N.B. - Google and python both insist that 999999.998 / 999 is 1001.000999
+  // However, multiplying the result back, 999 * 1001.000998999 gives the
+  // original value exactly, while their answer does not, 999 * 10001.000999 =
+  // 999999.998001. The same issue comes up many times during the following
+  // computations.  Division is hard, let's go shopping.
+  { "cast(999999.998 as decimal(9,3)) / 999",
+    {{ false, 1001000998998, 15, 9 },
+     { false, 1001000998999, 15, 9 }}},
+  { "cast(999.999998 as decimal(9,3)) / 999",
+    {{ false, 1001000000, 15, 9 },
+     { false, 1001001001, 15, 9 }}},
+  { "cast(999.999998 as decimal(9,6)) / 999",
+    {{ false, 1001000998998, 15, 12 },
+     { false, 1001000998999, 15, 12 }}},
+  { "cast(0.999999998 as decimal(9,6)) / 999",
+    {{ false, 1001000000, 15, 12 },
+     { false, 1001001001, 15, 12 }}},
+  { "cast(0.999999998 as decimal(9,9)) / 999",
+    {{ false, 1001000998998, 15, 15 },
+     { false, 1001000998999, 15, 15 }}},
+  { "cast(-999999.998 as decimal(9,3)) / 999",
+    {{ false, -1001000998998, 15, 9 },
+     { false, -1001000998999, 15, 9 }}},
+  { "cast(-999.999998 as decimal(9,3)) / 999",
+    {{ false, -1001000000, 15, 9 },
+     { false, -1001001001, 15, 9 }}},
+  { "cast(-999.999998 as decimal(9,6)) / 999",
+    {{ false, -1001000998998, 15, 12 },
+     { false, -1001000998999, 15, 12 }}},
+  { "cast(-0.999999998 as decimal(9,6)) / 999",
+    {{ false, -1001000000, 15, 12 },
+     { false, -1001001001, 15, 12 }}},
+  { "cast(-0.999999998 as decimal(9,9)) / 999",
+    {{ false, -1001000998998, 15, 15 },
+     { false, -1001000998999, 15, 15 }}},
+  { "cast(-999999.998 as decimal(9,3)) / -999",
+    {{ false, 1001000998998, 15, 9 },
+     { false, 1001000998999, 15, 9 }}},
+  { "cast(-999.999998 as decimal(9,3)) / -999",
+    {{ false, 1001000000, 15, 9 },
+     { false, 1001001001, 15, 9 }}},
+  { "cast(-999.999998 as decimal(9,6)) / -999",
+    {{ false, 1001000998998, 15, 12 },
+     { false, 1001000998999, 15, 12 }}},
+  { "cast(-0.999999998 as decimal(9,6)) / -999",
+    {{ false, 1001000000, 15, 12 },
+     { false, 1001001001, 15, 12 }}},
+  { "cast(-0.999999998 as decimal(9,9)) / -999",
+    {{ false, 1001000998998, 15, 15 },
+     { false, 1001000998999, 15, 15 }}},
+  { "cast(999999.998 as decimal(9,3)) / -999",
+    {{ false, -1001000998998, 15, 9 },
+     { false, -1001000998999, 15, 9 }}},
+  { "cast(999.999998 as decimal(9,3)) / -999",
+    {{ false, -1001000000, 15, 9 },
+     { false, -1001001001, 15, 9 }}},
+  { "cast(999.999998 as decimal(9,6)) / -999",
+    {{ false, -1001000998998, 15, 12 },
+     { false, -1001000998999, 15, 12 }}},
+  { "cast(0.999999998 as decimal(9,6)) / -999",
+    {{ false, -1001000000, 15, 12 },
+     { false, -1001001001, 15, 12 }}},
+  { "cast(0.999999998 as decimal(9,9)) / -999",
+    {{ false, -1001000998998, 15, 15 },
+     { false, -1001000998999, 15, 15 }}},
+  { "cast(999.999998 as decimal(9,3)) / 999999999",
+    {{ false, 99999900, 20, 14 },
+     { false, 100000000, 20, 14 }}},
+  { "cast(999.999998 as decimal(9,6)) / 999999999",
+    {{ false, 99999999899, 20, 17 },
+     { false, 99999999900, 20, 17 }}},
+  { "cast(0.999999998 as decimal(9,6)) / 999999999",
+    {{ false, 99999900, 20, 17 },
+     { false, 100000000, 20, 17 }}},
+  { "cast(0.999999998 as decimal(9,9)) / 999999999",
+    {{ false, 99999999899, 20, 20 },
+     { false, 99999999900, 20, 20 }}},
+  { "cast(-999999.998 as decimal(9,3)) / 999999999",
+    {{ false, -99999999899, 20, 14 },
+     { false, -99999999900, 20, 14 }}},
+  { "cast(-999.999998 as decimal(9,3)) / 999999999",
+    {{ false, -99999900, 20, 14 },
+     { false, -100000000, 20, 14 }}},
+  { "cast(-999.999998 as decimal(9,6)) / 999999999",
+    {{ false, -99999999899, 20, 17 },
+     { false, -99999999900, 20, 17 }}},
+  { "cast(-0.999999998 as decimal(9,6)) / 999999999",
+    {{ false, -99999900, 20, 17 },
+     { false, -100000000, 20, 17 }}},
+  { "cast(-0.999999998 as decimal(9,9)) / 999999999",
+    {{ false, -99999999899, 20, 20 },
+     { false, -99999999900, 20, 20 }}},
+  { "cast(-999999.998 as decimal(9,3)) / 999999999",
+    {{ false, -99999999899, 20, 14 },
+     { false, -99999999900, 20, 14 }}},
+  { "cast(-999.999998 as decimal(9,3)) / 999999999",
+    {{ false, -99999900, 20, 14 },
+     { false, -100000000, 20, 14 }}},
+  { "cast(-999.999998 as decimal(9,6)) / 999999999",
+    {{ false, -99999999899, 20, 17 },
+     { false, -99999999900, 20, 17 }}},
+  { "cast(-0.999999998 as decimal(9,6)) / 999999999",
+    {{ false, -99999900, 20, 17 },
+     { false, -100000000, 20, 17 }}},
+  { "cast(-0.999999998 as decimal(9,9)) / 999999999",
+    {{ false, -99999999899, 20, 20 },
+     { false, -99999999900, 20, 20 }}},
+  { "cast(999999.998 as decimal(9,3)) / -999999999",
+    {{ false, -99999999899, 20, 14 },
+     { false, -99999999900, 20, 14 }}},
+  { "cast(999.999998 as decimal(9,3)) / -999999999",
+    {{ false, -99999900, 20, 14 },
+     { false, -100000000, 20, 14 }}},
+  { "cast(999.999998 as decimal(9,6)) / -999999999",
+    {{ false, -99999999899, 20, 17 },
+     { false, -99999999900, 20, 17 }}},
+  { "cast(0.999999998 as decimal(9,6)) / -999999999",
+    {{ false, -99999900, 20, 17 },
+     { false, -100000000, 20, 17 }}},
+  { "cast(0.999999998 as decimal(9,9)) / -999999999",
+    {{ false, -99999999899, 20, 20 },
+     { false, -99999999900, 20, 20 }}},
+  { 
"17014118346046923173168730371588.410/17014118346046923173168730371588.410",
+    {{ false, 1000, 38, 3 },
+     { false, 1000000, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/17014118346046923173168730371588.409",
+    {{ false, 1000, 38, 3 },
+     { false, 1000000, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 3 },
+     { false, 1, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/34028236692093846346337460743176820001",
+    {{ false, 0, 38, 3 },
+     { false, 0, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/51042355038140769519506191114765230000",
+    {{ false, 0, 38, 3 },
+     { false, 0, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/10208471007628153903901238222953046343",
+    {{ false, 0, 38, 3 },
+     { false, 2, 38, 6 }}},
+  { 
"170141183460469231731687303715884.10/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 2 },
+     { false, 5, 38, 6 }}},
+  { 
"170141183460469231731687303715884.10/34028236692093846346337460743176820001",
+    {{ false, 0, 38, 2 },
+     { false, 5, 38, 6 }}},
+  { 
"170141183460469231731687303715884.10/51042355038140769519506191114765230000",
+    {{ false, 0, 38, 2 },
+     { false, 3, 38, 6 }}},
+  { 
"170141183460469231731687303715884.10/10208471007628153903901238222953046343",
+    {{ false, 0, 38, 2 },
+     { false, 17, 38, 6 }}},
+  { 
"1701411834604692317316873037158841.0/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 1 },
+     { false, 50, 38, 6 }}},
+  { 
"1701411834604692317316873037158841.0/34028236692093846346337460743176820001",
+    {{ false, 0, 38, 1 },
+     { false, 50, 38, 6 }}},
+  { 
"1701411834604692317316873037158841.0/51042355038140769519506191114765229999",
+    {{ false, 0, 38, 1 },
+     { false, 33, 38, 6 }}},
+  { 
"1701411834604692317316873037158841.0/10208471007628153903901238222953046343",
+    {{ false, 0, 38, 1 },
+     { false, 167, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 0 },
+     { false, 500, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/34028236692093846346337460743176820001",
+    {{ false, 0, 38, 0 },
+     { false, 500, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/51042355038140769519506191114765229999",
+    {{ false, 0, 38, 0 },
+     { false, 333, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/10208471007628153903901238222953046343",
+    {{ false, 0, 38, 0 },
+     { false, 1667, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/3402823669209384634633746074317682000.0",
+    {{ false, 0, 38, 1 },
+     { false, 5000, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/3402823669209384634633746074317682000.1",
+    {{ false, 0, 38, 1 },
+     { false, 5000, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/5104235503814076951950619111476522999.9",
+    {{ false, 0, 38, 1 },
+     { false, 3333, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/1020847100762815390390123822295304634.3",
+    {{ false, 0, 38, 1 },
+     { false, 16667, 38, 6 }}},
+  { 
"15014118346046923173168730371588.410/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 3 },
+     { false, 0, 38, 6 }}},
+  { 
"150141183460469231731687303715884.10/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 2 },
+     { false, 4, 38, 6 }}},
+  { 
"1501411834604692317316873037158841.0/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 1 },
+     { false, 44, 38, 6 }}},
+  { 
"15014118346046923173168730371588410/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 0 },
+     { false, 441, 38, 6 }}},
+  { 
"16014118346046923173168730371588.410/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 3 },
+     { false, 0, 38, 6 }}},
+  { 
"160141183460469231731687303715884.10/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 2 },
+     { false, 5, 38, 6 }}},
+  { 
"1601411834604692317316873037158841.0/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 1 },
+     { false, 47, 38, 6 }}},
+  { 
"16014118346046923173168730371588410/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 0 },
+     { false, 471, 38, 6 }}},
+  { 
"16014118346046923173168730371588410/3402823669209384634633746074317682000",
+    {{ false, 0, 38, 0 },
+     { false, 4706, 38, 6 }}},
+  { 
"18014118346046923173168730371588.410/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 3 },
+     { false, 1, 38, 6 }}},
+  { 
"180141183460469231731687303715884.10/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 2 },
+     { false, 5, 38, 6 }}},
+  { 
"1801411834604692317316873037158841.0/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 1 },
+     { false, 53, 38, 6 }}},
+  { 
"18014118346046923173168730371588410/34028236692093846346337460743176820000",
+    {{ false, 0, 38, 0 },
+     { false, 529, 38, 6 }}},
+  { 
"18014118346046923173168730371588410/3402823669209384634633746074317682000",
+    {{ false, 0, 38, 0 },
+     { false, 5294, 38, 6 }}},
+  { "18014118346046923173168730371588410/340282366920938463463374607431768200",
+    {{ false, 0, 38, 0 },
+     { false, 52939, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/-17014118346046923173168730371588.410",
+    {{ false, -1000, 38, 3 },
+     { false, -1000000, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/-17014118346046923173168730371588.409",
+    {{ false, -1000, 38, 3 },
+     { false, -1000000, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 3 },
+     { false, -1, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/-34028236692093846346337460743176820001",
+    {{ false, 0, 38, 3 },
+     { false, 0, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/-51042355038140769519506191114765230000",
+    {{ false, 0, 38, 3 },
+     { false, 0, 38, 6 }}},
+  { 
"17014118346046923173168730371588.410/-10208471007628153903901238222953046343",
+    {{ false, 0, 38, 3 },
+     { false, -2, 38, 6 }}},
+  { 
"170141183460469231731687303715884.10/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 2 },
+     { false, -5, 38, 6 }}},
+  { 
"170141183460469231731687303715884.10/-34028236692093846346337460743176820001",
+    {{ false, 0, 38, 2 },
+     { false, -5, 38, 6 }}},
+  { 
"170141183460469231731687303715884.10/-51042355038140769519506191114765230000",
+    {{ false, 0, 38, 2 },
+     { false, -3, 38, 6 }}},
+  { 
"170141183460469231731687303715884.10/-10208471007628153903901238222953046343",
+    {{ false, 0, 38, 2 },
+     { false, -17, 38, 6 }}},
+  { 
"1701411834604692317316873037158841.0/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 1 },
+     { false, -50, 38, 6 }}},
+  { 
"1701411834604692317316873037158841.0/-34028236692093846346337460743176820001",
+    {{ false, 0, 38, 1 },
+     { false, -50, 38, 6 }}},
+  { 
"1701411834604692317316873037158841.0/-51042355038140769519506191114765229999",
+    {{ false, 0, 38, 1 },
+     { false, -33, 38, 6 }}},
+  { 
"1701411834604692317316873037158841.0/-10208471007628153903901238222953046343",
+    {{ false, 0, 38, 1 },
+     { false, -167, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 0 },
+     { false, -500, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/-34028236692093846346337460743176820001",
+    {{ false, 0, 38, 0 },
+     { false, -500, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/-51042355038140769519506191114765229999",
+    {{ false, 0, 38, 0 },
+     { false, -333, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/-10208471007628153903901238222953046343",
+    {{ false, 0, 38, 0 },
+     { false, -1667, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/-3402823669209384634633746074317682000.0",
+    {{ false, 0, 38, 1 },
+     { false, -5000, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/-3402823669209384634633746074317682000.1",
+    {{ false, 0, 38, 1 },
+     { false, -5000, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/-5104235503814076951950619111476522999.9",
+    {{ false, 0, 38, 1 },
+     { false, -3333, 38, 6 }}},
+  { 
"17014118346046923173168730371588410/-1020847100762815390390123822295304634.3",
+    {{ false, 0, 38, 1 },
+     { false, -16667, 38, 6 }}},
+  { 
"15014118346046923173168730371588.410/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 3 },
+     { false, 0, 38, 6 }}},
+  { 
"150141183460469231731687303715884.10/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 2 },
+     { false, -4, 38, 6 }}},
+  { 
"1501411834604692317316873037158841.0/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 1 },
+     { false, -44, 38, 6 }}},
+  { 
"15014118346046923173168730371588410/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 0 },
+     { false, -441, 38, 6 }}},
+  { 
"16014118346046923173168730371588.410/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 3 },
+     { false, 0, 38, 6 }}},
+  { 
"160141183460469231731687303715884.10/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 2 },
+     { false, -5, 38, 6 }}},
+  { 
"1601411834604692317316873037158841.0/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 1 },
+     { false, -47, 38, 6 }}},
+  { 
"16014118346046923173168730371588410/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 0 },
+     { false, -471, 38, 6 }}},
+  { 
"16014118346046923173168730371588410/-3402823669209384634633746074317682000",
+    {{ false, 0, 38, 0 },
+     { false, -4706, 38, 6 }}},
+  { 
"18014118346046923173168730371588.410/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 3 },
+     { false, -1, 38, 6 }}},
+  { 
"180141183460469231731687303715884.10/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 2 },
+     { false, -5, 38, 6 }}},
+  { 
"1801411834604692317316873037158841.0/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 1 },
+     { false, -53, 38, 6 }}},
+  { 
"18014118346046923173168730371588410/-34028236692093846346337460743176820000",
+    {{ false, 0, 38, 0 },
+     { false, -529, 38, 6 }}},
+  { 
"18014118346046923173168730371588410/-3402823669209384634633746074317682000",
+    {{ false, 0, 38, 0 },
+     { false, -5294, 38, 6 }}},
+  { 
"18014118346046923173168730371588410/-340282366920938463463374607431768200",
+    {{ false, 0, 38, 0 },
+     { false, -52939, 38, 6 }}},
   // Test modulo operator
   { "cast(1.23 as decimal(8,2)) % cast(1 as decimal(10,3))", {{ false, 230, 9, 
3 }}},
   { "cast(1 as decimal(38,0)) % cast(.2 as decimal(38,1))", {{ false, 0, 38, 1 
}}},
@@ -1595,6 +1952,12 @@ DecimalTestCase decimal_cases[] = {
   { "cast(cast(-9223372036854775809.0 AS bigint) AS decimal(30,0))",
     {{ false, 9223372036854775807, 30, 0 }, // BUG: JIRA: IMPALA-865
      { true, 0, 30, 0 }}},
+  { "cast(cast(cast(pow(1, -38) as decimal(38,38)) as bigint) as 
decimal(18,10))",
+    {{ false, 0, 18, 10 },
+     { false, 10000000000, 18, 10 }}},
+  { "cast(cast(cast(-pow(1, -38) as decimal(38,38)) as bigint) as 
decimal(18,10))",
+    {{ false, 0, 18, 10 },
+     { false, -10000000000, 18, 10 }}},
   // Test CAST FLOAT -> DECIMAL
   { "cast(cast(power(10, 3) - power(10, -1) as float) as decimal(4,1))",
     {{ false, 9999, 4, 1 }}},

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/runtime/decimal-test.cc
----------------------------------------------------------------------
diff --git a/be/src/runtime/decimal-test.cc b/be/src/runtime/decimal-test.cc
index 6bcd34d..190ee39 100644
--- a/be/src/runtime/decimal-test.cc
+++ b/be/src/runtime/decimal-test.cc
@@ -34,7 +34,7 @@ using std::min;
 namespace impala {
 
 // Compare decimal result against double.
-static const double MAX_ERROR = 0.0001;
+static const double MAX_ERROR = 0.00005;
 
 template <typename T>
 void VerifyEquals(const DecimalValue<T>& t1, const DecimalValue<T>& t2) {
@@ -45,11 +45,11 @@ void VerifyEquals(const DecimalValue<T>& t1, const 
DecimalValue<T>& t2) {
 }
 
 template <typename T>
-void VerifyParse(const string& s, const ColumnType& t,
+void VerifyParse(const string& s, int precision, int scale,
     const DecimalValue<T>& expected_val, StringParser::ParseResult 
expected_result) {
   StringParser::ParseResult parse_result;
   DecimalValue<T> val = StringParser::StringToDecimal<T>(
-      s.c_str(), s.size(), t, &parse_result);
+      s.c_str(), s.size(), precision, scale, &parse_result);
   EXPECT_EQ(expected_result, parse_result) << "Failed test string: " << s;
   if (expected_result == StringParser::PARSE_SUCCESS ||
       expected_result == StringParser::PARSE_UNDERFLOW) {
@@ -58,31 +58,30 @@ void VerifyParse(const string& s, const ColumnType& t,
 }
 
 template<typename T>
-void VerifyToString(const T& decimal, const ColumnType& t, const string& 
expected) {
-  EXPECT_EQ(decimal.ToString(t), expected);
+void VerifyToString(const T& decimal, int precision, int scale, const string& 
expected) {
+  EXPECT_EQ(decimal.ToString(precision, scale), expected);
 }
 
-void StringToAllDecimals(const string& s, const ColumnType& t, int32_t val,
+void StringToAllDecimals(const string& s, int precision, int scale, int32_t 
val,
     StringParser::ParseResult result) {
-  VerifyParse(s, t, Decimal4Value(val), result);
-  VerifyParse(s, t, Decimal8Value(val), result);
-  VerifyParse(s, t, Decimal16Value(val), result);
+  VerifyParse(s, precision, scale, Decimal4Value(val), result);
+  VerifyParse(s, precision, scale, Decimal8Value(val), result);
+  VerifyParse(s, precision, scale, Decimal16Value(val), result);
 }
 
 TEST(IntToDecimal, Basic) {
   Decimal16Value d16;
   bool overflow = false;
 
-  d16 = Decimal16Value::FromInt(ColumnType::CreateDecimalType(27, 18), -25559, 
&overflow);
+  d16 = Decimal16Value::FromInt(27, 18, -25559, &overflow);
   EXPECT_FALSE(overflow);
-  VerifyToString(d16, ColumnType::CreateDecimalType(27, 18), 
"-25559.000000000000000000");
+  VerifyToString(d16, 27, 18, "-25559.000000000000000000");
 
-  d16 = Decimal16Value::FromInt(ColumnType::CreateDecimalType(36, 29), 32130, 
&overflow);
+  d16 = Decimal16Value::FromInt(36, 29, 32130, &overflow);
   EXPECT_FALSE(overflow);
-  VerifyToString(d16, ColumnType::CreateDecimalType(36, 29),
-      "32130.00000000000000000000000000000");
+  VerifyToString(d16, 36, 29, "32130.00000000000000000000000000000");
 
-  d16 = Decimal16Value::FromInt(ColumnType::CreateDecimalType(38, 38), 1, 
&overflow);
+  d16 = Decimal16Value::FromInt(38, 38, 1, &overflow);
   EXPECT_TRUE(overflow);
 
   // Smaller decimal types can't overflow here since the FE should never 
generate
@@ -90,363 +89,335 @@ TEST(IntToDecimal, Basic) {
 }
 
 TEST(DoubleToDecimal, Basic) {
-  ColumnType t1 = ColumnType::CreateDecimalType(9, 0);
-  ColumnType t2 = ColumnType::CreateDecimalType(10, 5);
-  ColumnType t3 = ColumnType::CreateDecimalType(10, 10);
-  ColumnType t4 = ColumnType::CreateDecimalType(1, 0);
-  ColumnType t5 = ColumnType::CreateDecimalType(1, 1);
-
   Decimal4Value d4;
   Decimal8Value d8;
   Decimal16Value d16;
 
   bool overflow = false;
-  d4 = Decimal4Value::FromDouble(t1, 1.9, true, &overflow);
+  d4 = Decimal4Value::FromDouble(9, 0, 1.9, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 2);
-  VerifyToString(d4, t1, "2");
+  VerifyToString(d4, 9, 0, "2");
 
-  d4 = Decimal4Value::FromDouble(t1, 1.9, false, &overflow);
+  d4 = Decimal4Value::FromDouble(9, 0, 1.9, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 1);
-  VerifyToString(d4, t1, "1");
+  VerifyToString(d4, 9, 0, "1");
 
-  d4 = Decimal4Value::FromDouble(t4, 1, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, 1, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 1);
-  VerifyToString(d4, t4, "1");
+  VerifyToString(d4, 1, 0, "1");
 
-  d4 = Decimal4Value::FromDouble(t4, 0, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, 0, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 0);
-  VerifyToString(d4, t4, "0");
+  VerifyToString(d4, 1, 0, "0");
 
-  d4 = Decimal4Value::FromDouble(t4, 9.9, false, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, 9.9, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 9);
-  VerifyToString(d4, t4, "9");
+  VerifyToString(d4, 1, 0, "9");
 
-  d4 = Decimal4Value::FromDouble(t4, 9.9, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, 9.9, true, &overflow);
   EXPECT_TRUE(overflow);
   overflow = false;
 
-  d4 = Decimal4Value::FromDouble(t4, -1, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, -1, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), -1);
-  VerifyToString(d4, t4, "-1");
+  VerifyToString(d4, 1, 0, "-1");
 
-  d4 = Decimal4Value::FromDouble(t4, -9.9, false, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, -9.9, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), -9);
-  VerifyToString(d4, t4, "-9");
+  VerifyToString(d4, 1, 0, "-9");
 
-  d4 = Decimal4Value::FromDouble(t4, -9.9, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, -9.9, true, &overflow);
   EXPECT_TRUE(overflow);
   overflow = false;
 
-  d4 = Decimal4Value::FromDouble(t5, 0.1, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 1, 0.1, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 1);
-  VerifyToString(d4, t5, "0.1");
+  VerifyToString(d4, 1, 1, "0.1");
 
-  d4 = Decimal4Value::FromDouble(t5, 0.0, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 1, 0.0, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 0);
-  VerifyToString(d4, t5, "0.0");
+  VerifyToString(d4, 1, 1, "0.0");
 
-  d4 = Decimal4Value::FromDouble(t5, -0.1, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 1, -0.1, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), -1);
-  VerifyToString(d4, t5, "-0.1");
+  VerifyToString(d4, 1, 1, "-0.1");
 
   overflow = false;
-  d8 = Decimal8Value::FromDouble(t2, -100.1, true, &overflow);
+  d8 = Decimal8Value::FromDouble(10, 5, -100.1, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d8.value(), -10010000);
-  VerifyToString(d8, t2, "-100.10000");
+  VerifyToString(d8, 10, 5, "-100.10000");
 
   overflow = false;
-  d16 = Decimal16Value::FromDouble(t3, -0.1, true, &overflow);
+  d16 = Decimal16Value::FromDouble(10, 10, -0.1, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d16.value(), -1000000000);
-  VerifyToString(d16, t3, "-0.1000000000");
+  VerifyToString(d16, 10, 10, "-0.1000000000");
 
   // Test overflow
   overflow = false;
-  Decimal4Value::FromDouble(t1, 999999999.123, false, &overflow);
+  Decimal4Value::FromDouble(9, 0, 999999999.123, false, &overflow);
   EXPECT_FALSE(overflow);
 
   overflow = false;
-  Decimal4Value::FromDouble(t1, 1234567890.1, false, &overflow);
+  Decimal4Value::FromDouble(9, 0, 1234567890.1, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  Decimal8Value::FromDouble(t1, -1234567890.123, false, &overflow);
+  Decimal8Value::FromDouble(9, 0, -1234567890.123, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  Decimal8Value::FromDouble(t2, 99999.1234567, false, &overflow);
+  Decimal8Value::FromDouble(10, 5, 99999.1234567, false, &overflow);
   EXPECT_FALSE(overflow);
 
   overflow = false;
-  Decimal8Value::FromDouble(t2, 100000.1, false, &overflow);
+  Decimal8Value::FromDouble(10, 5, 100000.1, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  Decimal8Value::FromDouble(t2, -123456.123, false, &overflow);
+  Decimal8Value::FromDouble(10, 5, -123456.123, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  d16 = Decimal16Value::FromDouble(t3, 0.1234, true, &overflow);
+  d16 = Decimal16Value::FromDouble(10, 10, 0.1234, true, &overflow);
   EXPECT_FALSE(overflow);
-  VerifyToString(d16, t3, "0.1234000000");
+  VerifyToString(d16, 10, 10, "0.1234000000");
 
   overflow = false;
-  Decimal16Value::FromDouble(t3, 1.1, true, &overflow);
+  Decimal16Value::FromDouble(10, 10, 1.1, true, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  Decimal16Value::FromDouble(t3, -1.1, true, &overflow);
+  Decimal16Value::FromDouble(10, 10, -1.1, true, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  Decimal16Value::FromDouble(t3, 0.99999999999, false, &overflow);
+  Decimal16Value::FromDouble(10, 10, 0.99999999999, false, &overflow);
   EXPECT_FALSE(overflow);
 
   overflow = false;
-  Decimal16Value::FromDouble(t3, 0.99999999999, true, &overflow);
+  Decimal16Value::FromDouble(10, 10, 0.99999999999, true, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  Decimal16Value::FromDouble(t3, -0.99999999999, false, &overflow);
+  Decimal16Value::FromDouble(10, 10, -0.99999999999, false, &overflow);
   EXPECT_FALSE(overflow);
 
   overflow = false;
-  Decimal16Value::FromDouble(t3, -0.99999999999, true, &overflow);
+  Decimal16Value::FromDouble(10, 10, -0.99999999999, true, &overflow);
   EXPECT_TRUE(overflow);
   overflow = false;
 
   // Test half rounding behavior
-  d4 = Decimal4Value::FromDouble(t4, 0.499999999, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, 0.499999999, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 0);
-  VerifyToString(d4, t4, "0");
+  VerifyToString(d4, 1, 0, "0");
 
-  d4 = Decimal4Value::FromDouble(t4, 0.5, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, 0.5, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 1);
-  VerifyToString(d4, t4, "1");
+  VerifyToString(d4, 1, 0, "1");
 
-  d4 = Decimal4Value::FromDouble(t4, -0.499999999, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, -0.499999999, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), 0);
-  VerifyToString(d4, t4, "0");
+  VerifyToString(d4, 1, 0, "0");
 
-  d4 = Decimal4Value::FromDouble(t4, -0.5, true, &overflow);
+  d4 = Decimal4Value::FromDouble(1, 0, -0.5, true, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(d4.value(), -1);
-  VerifyToString(d4, t4, "-1");
+  VerifyToString(d4, 1, 0, "-1");
 }
 
 TEST(StringToDecimal, Basic) {
-  ColumnType t1 = ColumnType::CreateDecimalType(10, 0);
-  ColumnType t2 = ColumnType::CreateDecimalType(10, 2);
-  ColumnType t3 = ColumnType::CreateDecimalType(2, 0);
-  ColumnType t4 = ColumnType::CreateDecimalType(10, 5);
-
-  StringToAllDecimals("       1234", t1, 1234, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("   ", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals(" 0 0 ", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0 0", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("++0", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("--0", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("..0", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0..", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals(".0.", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0.0.", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0-", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0+", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("X", t1, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("+", t3, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("-", t3, 0, StringParser::PARSE_FAILURE);
-
-  StringToAllDecimals("1234", t1, 1234, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("1234", t2, 123400, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-1234", t2, -123400, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("123", t3, 123, StringParser::PARSE_OVERFLOW);
-  StringToAllDecimals("  12  ", t3, 12, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("000", t3, 0, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals(" . ", t3, 0, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-.", t3, 0, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("1.", t3, 1, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals(".1", t2, 10, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("00012.3", t2, 1230, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-00012.3", t2, -1230, StringParser::PARSE_SUCCESS);
-
-  StringToAllDecimals("123.45", t2, 12345, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals(".45", t2, 45, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-.45", t2, -45, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals(" 123.4 ", t4, 12340000, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-123.45", t4, -12345000, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-123.456", t2, -12345, StringParser::PARSE_UNDERFLOW);
-
-  StringToAllDecimals("e", t3, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("E", t3, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("+E", t3, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals(".E", t3, 0, StringParser::PARSE_FAILURE);
-  StringToAllDecimals(" 0 e 0 ", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0e 0", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0e1.0", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0e1.", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0e.1", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("0ee0", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("e1", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("1e", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("1.1.0e0", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("1e1.0", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("1..1e1", t1, 100, StringParser::PARSE_FAILURE);
-  StringToAllDecimals("1e9999999999999999999", t1, 100, 
StringParser::PARSE_OVERFLOW);
-
-  StringToAllDecimals(" 1e0 ", t2, 100, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-1e0", t2, -100, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("1e-0", t2, 100, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals(" 1e2 ", t2, 10000, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-1e-2", t2, -1, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals(".011e3 ", t3, 11, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals(".00011e5 ", t3, 11, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("110e-1 ", t3, 11, StringParser::PARSE_UNDERFLOW);
-  StringToAllDecimals("1.10e1 ", t3, 11, StringParser::PARSE_UNDERFLOW);
-  StringToAllDecimals("1.10e3 ", t3, 11, StringParser::PARSE_OVERFLOW);
+  StringToAllDecimals("       1234", 10, 0, 1234, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("   ", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals(" 0 0 ", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0 0", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("++0", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("--0", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("..0", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0..", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals(".0.", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0.0.", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0-", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0+", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("X", 10, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("+", 2, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("-", 2, 0, 0, StringParser::PARSE_FAILURE);
+
+  StringToAllDecimals("1234", 10, 0, 1234, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("1234", 10, 2, 123400, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-1234", 10, 2, -123400, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("123", 2, 0, 123, StringParser::PARSE_OVERFLOW);
+  StringToAllDecimals("  12  ", 2, 0, 12, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("000", 2, 0, 0, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals(" . ", 2, 0, 0, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-.", 2, 0, 0, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("1.", 2, 0, 1, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals(".1", 10, 2, 10, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("00012.3", 10, 2, 1230, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-00012.3", 10, 2, -1230, StringParser::PARSE_SUCCESS);
+
+  StringToAllDecimals("123.45", 10, 2, 12345, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals(".45", 10, 2, 45, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-.45", 10, 2, -45, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals(" 123.4 ", 10, 5, 12340000, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-123.45", 10, 5, -12345000, 
StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-123.456", 10, 2, -12345, 
StringParser::PARSE_UNDERFLOW);
+
+  StringToAllDecimals("e", 2, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("E", 2, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("+E", 2, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals(".E", 2, 0, 0, StringParser::PARSE_FAILURE);
+  StringToAllDecimals(" 0 e 0 ", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0e 0", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0e1.0", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0e1.", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0e.1", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("0ee0", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("e1", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("1e", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("1.1.0e0", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("1e1.0", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("1..1e1", 10, 0, 100, StringParser::PARSE_FAILURE);
+  StringToAllDecimals("1e9999999999999999999", 10, 0, 100, 
StringParser::PARSE_OVERFLOW);
+
+  StringToAllDecimals(" 1e0 ", 10, 2, 100, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-1e0", 10, 2, -100, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("1e-0", 10, 2, 100, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals(" 1e2 ", 10, 2, 10000, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-1e-2", 10, 2, -1, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals(".011e3 ", 2, 0, 11, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals(".00011e5 ", 2, 0, 11, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("110e-1 ", 2, 0, 11, StringParser::PARSE_UNDERFLOW);
+  StringToAllDecimals("1.10e1 ", 2, 0, 11, StringParser::PARSE_UNDERFLOW);
+  StringToAllDecimals("1.10e3 ", 2, 0, 11, StringParser::PARSE_OVERFLOW);
 }
 
 TEST(StringToDecimal, LargeDecimals) {
-  ColumnType t1 = ColumnType::CreateDecimalType(1, 0);
-  ColumnType t2 = ColumnType::CreateDecimalType(10, 10);
-  ColumnType t3 = ColumnType::CreateDecimalType(8, 3);
-
-  StringToAllDecimals("1", t1, 1, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals("-1", t1, -1, StringParser::PARSE_SUCCESS);
-  StringToAllDecimals(".1", t1, 0, StringParser::PARSE_UNDERFLOW);
-  StringToAllDecimals("10", t1, 10, StringParser::PARSE_OVERFLOW);
-  StringToAllDecimals("-10", t1, -10, StringParser::PARSE_OVERFLOW);
+  StringToAllDecimals("1", 1, 0, 1, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals("-1", 1, 0, -1, StringParser::PARSE_SUCCESS);
+  StringToAllDecimals(".1", 1, 0, 0, StringParser::PARSE_UNDERFLOW);
+  StringToAllDecimals("10", 1, 0, 10, StringParser::PARSE_OVERFLOW);
+  StringToAllDecimals("-10", 1, 0, -10, StringParser::PARSE_OVERFLOW);
 
-  VerifyParse(".1234567890", t2,
+  VerifyParse(".1234567890", 10, 10,
       Decimal8Value(1234567890L), StringParser::PARSE_SUCCESS);
-  VerifyParse("-.1234567890", t2,
+  VerifyParse("-.1234567890", 10, 10,
       Decimal8Value(-1234567890L), StringParser::PARSE_SUCCESS);
-  VerifyParse(".12345678900", t2,
+  VerifyParse(".12345678900", 10, 10,
       Decimal8Value(1234567890L), StringParser::PARSE_UNDERFLOW);
-  VerifyParse("-.12345678900", t2,
+  VerifyParse("-.12345678900", 10, 10,
       Decimal8Value(-1234567890L), StringParser::PARSE_UNDERFLOW);
-  VerifyParse(".1234567890", t2,
+  VerifyParse(".1234567890", 10, 10,
       Decimal16Value(1234567890L), StringParser::PARSE_SUCCESS);
-  VerifyParse("-.1234567890", t2,
+  VerifyParse("-.1234567890", 10, 10,
       Decimal16Value(-1234567890L), StringParser::PARSE_SUCCESS);
-  VerifyParse(".12345678900", t2,
+  VerifyParse(".12345678900", 10, 10,
       Decimal16Value(1234567890L), StringParser::PARSE_UNDERFLOW);
-  VerifyParse("-.12345678900", t2,
+  VerifyParse("-.12345678900", 10, 10,
       Decimal16Value(-1234567890L), StringParser::PARSE_UNDERFLOW);
 
   // Up to 8 digits with 5 before the decimal and 3 after.
-  VerifyParse("12345.678", t3,
+  VerifyParse("12345.678", 8, 3,
       Decimal8Value(12345678L), StringParser::PARSE_SUCCESS);
-  VerifyParse("-12345.678", t3,
+  VerifyParse("-12345.678", 8, 3,
       Decimal8Value(-12345678L), StringParser::PARSE_SUCCESS);
-  VerifyParse("123456.78", t3,
+  VerifyParse("123456.78", 8, 3,
       Decimal8Value(12345678L), StringParser::PARSE_OVERFLOW);
-  VerifyParse("1234.5678", t3,
+  VerifyParse("1234.5678", 8, 3,
       Decimal8Value(1234567L), StringParser::PARSE_UNDERFLOW);
-  VerifyParse("12345.678", t3,
+  VerifyParse("12345.678", 8, 3,
       Decimal16Value(12345678L), StringParser::PARSE_SUCCESS);
-  VerifyParse("-12345.678", t3,
+  VerifyParse("-12345.678", 8, 3,
       Decimal16Value(-12345678L), StringParser::PARSE_SUCCESS);
-  VerifyParse("123456.78", t3,
+  VerifyParse("123456.78", 8, 3,
       Decimal16Value(12345678L), StringParser::PARSE_OVERFLOW);
-  VerifyParse("1234.5678", t3,
+  VerifyParse("1234.5678", 8, 3,
       Decimal16Value(1234567L), StringParser::PARSE_UNDERFLOW);
 
   // Test max unscaled value for each of the decimal types.
-  VerifyParse("999999999", ColumnType::CreateDecimalType(9, 0),
+  VerifyParse("999999999", 9, 0,
       Decimal4Value(999999999), StringParser::PARSE_SUCCESS);
-  VerifyParse("99999.9999", ColumnType::CreateDecimalType(9, 4),
+  VerifyParse("99999.9999", 9, 4,
       Decimal4Value(999999999), StringParser::PARSE_SUCCESS);
-  VerifyParse("0.999999999", ColumnType::CreateDecimalType(9, 9),
+  VerifyParse("0.999999999", 9, 9,
       Decimal4Value(999999999), StringParser::PARSE_SUCCESS);
-  VerifyParse("-999999999", ColumnType::CreateDecimalType(9, 0),
+  VerifyParse("-999999999", 9, 0,
       Decimal4Value(-999999999), StringParser::PARSE_SUCCESS);
-  VerifyParse("-99999.9999", ColumnType::CreateDecimalType(9, 4),
+  VerifyParse("-99999.9999", 9, 4,
       Decimal4Value(-999999999), StringParser::PARSE_SUCCESS);
-  VerifyParse("-0.999999999", ColumnType::CreateDecimalType(9, 9),
+  VerifyParse("-0.999999999", 9, 9,
       Decimal4Value(-999999999), StringParser::PARSE_SUCCESS);
-  VerifyParse("1000000000", ColumnType::CreateDecimalType(9, 0),
+  VerifyParse("1000000000", 9, 0,
       Decimal4Value(0), StringParser::PARSE_OVERFLOW);
-  VerifyParse("-1000000000", ColumnType::CreateDecimalType(9, 0),
+  VerifyParse("-1000000000", 9, 0,
       Decimal4Value(0), StringParser::PARSE_OVERFLOW);
 
-  VerifyParse("999999999999999999", ColumnType::CreateDecimalType(18, 0),
+  VerifyParse("999999999999999999", 18, 0,
       Decimal8Value(999999999999999999ll), StringParser::PARSE_SUCCESS);
-  VerifyParse("999999.999999999999", ColumnType::CreateDecimalType(18, 12),
+  VerifyParse("999999.999999999999", 18, 12,
       Decimal8Value(999999999999999999ll), StringParser::PARSE_SUCCESS);
-  VerifyParse(".999999999999999999", ColumnType::CreateDecimalType(18, 18),
+  VerifyParse(".999999999999999999", 18, 18,
       Decimal8Value(999999999999999999ll), StringParser::PARSE_SUCCESS);
-  VerifyParse("-999999999999999999", ColumnType::CreateDecimalType(18, 0),
+  VerifyParse("-999999999999999999", 18, 0,
       Decimal8Value(-999999999999999999ll), StringParser::PARSE_SUCCESS);
-  VerifyParse("-999999.999999999999", ColumnType::CreateDecimalType(18, 12),
+  VerifyParse("-999999.999999999999", 18, 12,
       Decimal8Value(-999999999999999999ll), StringParser::PARSE_SUCCESS);
-  VerifyParse("-.999999999999999999", ColumnType::CreateDecimalType(18, 18),
+  VerifyParse("-.999999999999999999", 18, 18,
       Decimal8Value(-999999999999999999ll), StringParser::PARSE_SUCCESS);
-  VerifyParse("1000000000000000000", ColumnType::CreateDecimalType(18, 0),
+  VerifyParse("1000000000000000000", 18, 0,
       Decimal8Value(0), StringParser::PARSE_OVERFLOW);
-  VerifyParse("01000000000000000000", ColumnType::CreateDecimalType(18, 0),
+  VerifyParse("01000000000000000000", 18, 0,
       Decimal8Value(0), StringParser::PARSE_OVERFLOW);
 
   int128_t result = DecimalUtil::MAX_UNSCALED_DECIMAL16;
   VerifyParse("99999999999999999999999999999999999999",
-      ColumnType::CreateDecimalType(38, 0),
-      Decimal16Value(result), StringParser::PARSE_SUCCESS);
+      38, 0, Decimal16Value(result), StringParser::PARSE_SUCCESS);
   VerifyParse("99999999999999999999999999999999999999e1",
-      ColumnType::CreateDecimalType(38, 0),
-      Decimal16Value(result), StringParser::PARSE_OVERFLOW);
+      38, 0, Decimal16Value(result), StringParser::PARSE_OVERFLOW);
   VerifyParse("999999999999999999999999999999999999990e-1",
-      ColumnType::CreateDecimalType(38, 0),
-      Decimal16Value(result), StringParser::PARSE_UNDERFLOW);
+      38, 0, Decimal16Value(result), StringParser::PARSE_UNDERFLOW);
   VerifyParse("999999999999999999999999999999999.99999",
-      ColumnType::CreateDecimalType(38, 5),
-      Decimal16Value(result), StringParser::PARSE_SUCCESS);
+      38, 5, Decimal16Value(result), StringParser::PARSE_SUCCESS);
   VerifyParse(".99999999999999999999999999999999999999",
-      ColumnType::CreateDecimalType(38, 38),
-      Decimal16Value(result), StringParser::PARSE_SUCCESS);
+      38, 38, Decimal16Value(result), StringParser::PARSE_SUCCESS);
   VerifyParse("-99999999999999999999999999999999999999",
-      ColumnType::CreateDecimalType(38, 0),
-      Decimal16Value(-result), StringParser::PARSE_SUCCESS);
+      38, 0, Decimal16Value(-result), StringParser::PARSE_SUCCESS);
   VerifyParse("-999999999999999999999999999999999.99999",
-      ColumnType::CreateDecimalType(38, 5),
-      Decimal16Value(-result), StringParser::PARSE_SUCCESS);
+      38, 5, Decimal16Value(-result), StringParser::PARSE_SUCCESS);
   VerifyParse("-.99999999999999999999999999999999999999",
-      ColumnType::CreateDecimalType(38, 38),
-      Decimal16Value(-result), StringParser::PARSE_SUCCESS);
+      38, 38, Decimal16Value(-result), StringParser::PARSE_SUCCESS);
   VerifyParse("-.99999999999999999999999999999999999999e1",
-      ColumnType::CreateDecimalType(38, 38),
-      Decimal16Value(-result), StringParser::PARSE_OVERFLOW);
+      38, 38, Decimal16Value(-result), StringParser::PARSE_OVERFLOW);
   VerifyParse("-.999999999999999999999999999999999999990e-1",
-      ColumnType::CreateDecimalType(38, 38),
-      Decimal16Value(-result / 10), StringParser::PARSE_UNDERFLOW);
+      38, 38, Decimal16Value(-result / 10), StringParser::PARSE_UNDERFLOW);
   VerifyParse("-.999999999999999999999999999999999999990000000000000000e-20",
-      ColumnType::CreateDecimalType(38, 38),
+      38, 38,
       Decimal16Value(-result / DecimalUtil::GetScaleMultiplier<int128_t>(20)),
       StringParser::PARSE_UNDERFLOW);
   VerifyParse("100000000000000000000000000000000000000",
-      ColumnType::CreateDecimalType(38, 0),
-      Decimal16Value(0), StringParser::PARSE_OVERFLOW);
+      38, 0, Decimal16Value(0), StringParser::PARSE_OVERFLOW);
   VerifyParse("-100000000000000000000000000000000000000",
-      ColumnType::CreateDecimalType(38, 0),
-      Decimal16Value(0), StringParser::PARSE_OVERFLOW);
+      38, 0, Decimal16Value(0), StringParser::PARSE_OVERFLOW);
 }
 
 TEST(DecimalTest, Overflow) {
   bool overflow = false;
-  ColumnType t1 = ColumnType::CreateDecimalType(38, 0);
 
   Decimal16Value result;
   Decimal16Value d_max(DecimalUtil::MAX_UNSCALED_DECIMAL16);
@@ -456,157 +427,155 @@ TEST(DecimalTest, Overflow) {
 
   // Adding same sign
   overflow = false;
-  d_max.Add<int128_t>(t1, one, t1, 38, 0, &overflow);
+  d_max.Add<int128_t>(0, one, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  one.Add<int128_t>(t1, d_max, t1, 38, 0, &overflow);
+  one.Add<int128_t>(0, d_max, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  d_max.Add<int128_t>(t1, d_max, t1, 38, 0, &overflow);
+  d_max.Add<int128_t>(0, d_max, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  result = d_max.Add<int128_t>(t1, zero, t1, 38, 0, &overflow);
+  result = d_max.Add<int128_t>(0, zero, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == d_max.value());
 
   // Subtracting same sign
   overflow = false;
-  result = d_max.Subtract<int128_t>(t1, one, t1, 38, 0, &overflow);
+  result = d_max.Subtract<int128_t>(0, one, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
 
   overflow = false;
   EXPECT_TRUE(result.value() == d_max.value() - 1);
-  result = one.Subtract<int128_t>(t1, d_max, t1, 38, 0, &overflow);
+  result = one.Subtract<int128_t>(0, d_max, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
 
   overflow = false;
   EXPECT_TRUE(result.value() == -(d_max.value() - 1));
-  result = d_max.Subtract<int128_t>(t1, d_max, t1, 38, 0, &overflow);
+  result = d_max.Subtract<int128_t>(0, d_max, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
 
   overflow = false;
   EXPECT_TRUE(result.value() == 0);
-  result = d_max.Subtract<int128_t>(t1, zero, t1, 38, 0, &overflow);
+  result = d_max.Subtract<int128_t>(0, zero, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == d_max.value());
 
   // Adding different sign
   overflow = false;
-  result = d_max.Add<int128_t>(t1, -one, t1, 38, 0, &overflow);
+  result = d_max.Add<int128_t>(0, -one, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == d_max.value() - 1);
 
   overflow = false;
-  result = one.Add<int128_t>(t1, -d_max, t1, 38, 0, &overflow);
+  result = one.Add<int128_t>(0, -d_max, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == -(d_max.value() - 1));
 
   overflow = false;
-  result = d_max.Add<int128_t>(t1, -d_max, t1, 38, 0, &overflow);
+  result = d_max.Add<int128_t>(0, -d_max, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == 0);
 
   overflow = false;
-  result = d_max.Add<int128_t>(t1, -zero, t1, 38, 0, &overflow);
+  result = d_max.Add<int128_t>(0, -zero, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == d_max.value());
 
   // Subtracting different sign
   overflow = false;
-  d_max.Subtract<int128_t>(t1, -one, t1, 38, 0, &overflow);
+  d_max.Subtract<int128_t>(0, -one, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
-  one.Subtract<int128_t>(t1, -d_max, t1, 38, 0, &overflow);
+  one.Subtract<int128_t>(0, -d_max, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  d_max.Subtract<int128_t>(t1, -d_max, t1, 38, 0, &overflow);
+  d_max.Subtract<int128_t>(0, -d_max, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  result = d_max.Subtract<int128_t>(t1, -zero, t1, 38, 0, &overflow);
+  result = d_max.Subtract<int128_t>(0, -zero, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == d_max.value());
 
   // Multiply
   overflow = false;
-  result = d_max.Multiply<int128_t>(t1, one, t1, 38, 0, &overflow);
+  result = d_max.Multiply<int128_t>(0, one, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == d_max.value());
 
   overflow = false;
-  result = d_max.Multiply<int128_t>(t1, -one, t1, 38, 0, &overflow);
+  result = d_max.Multiply<int128_t>(0, -one, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == -d_max.value());
 
   overflow = false;
-  result = d_max.Multiply<int128_t>(t1, two, t1, 38, 0, &overflow);
+  result = d_max.Multiply<int128_t>(0, two, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  result = d_max.Multiply<int128_t>(t1, -two, t1, 38, 0, &overflow);
+  result = d_max.Multiply<int128_t>(0, -two, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  result = d_max.Multiply<int128_t>(t1, d_max, t1, 38, 0, &overflow);
+  result = d_max.Multiply<int128_t>(0, d_max, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   overflow = false;
-  result = d_max.Multiply<int128_t>(t1, -d_max, t1, 38, 0, &overflow);
+  result = d_max.Multiply<int128_t>(0, -d_max, 0, 38, 0, false, &overflow);
   EXPECT_TRUE(overflow);
 
   // Multiply by 0
   overflow = false;
-  result = zero.Multiply<int128_t>(t1, one, t1, 38, 0, &overflow);
+  result = zero.Multiply<int128_t>(0, one, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == 0);
 
   overflow = false;
-  result = one.Multiply<int128_t>(t1, zero, t1, 38, 0, &overflow);
+  result = one.Multiply<int128_t>(0, zero, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == 0);
 
   overflow = false;
-  result = zero.Multiply<int128_t>(t1, zero, t1, 38, 0, &overflow);
+  result = zero.Multiply<int128_t>(0, zero, 0, 38, 0, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_TRUE(result.value() == 0);
 
   // Adding any value with scale to (38, 0) will overflow if the most 
significant
   // digit is set.
-  ColumnType t2 = ColumnType::CreateDecimalType(1, 1);
   overflow = false;
-  result = d_max.Add<int128_t>(t1, zero, t2, 38, 1, &overflow);
+  result = d_max.Add<int128_t>(0, zero, 1, 38, 1, false, &overflow);
   EXPECT_TRUE(overflow);
 
   // Add 37 9's (with scale 0)
   Decimal16Value d3(DecimalUtil::MAX_UNSCALED_DECIMAL16 / 10);
   overflow = false;
-  result = d3.Add<int128_t>(t1, zero, t2, 38, 1, &overflow);
+  result = d3.Add<int128_t>(0, zero, 1, 38, 1, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(result.value(), DecimalUtil::MAX_UNSCALED_DECIMAL16 - 9);
 
   overflow = false;
-  result = d3.Add<int128_t>(t1, one, t2, 38, 1, &overflow);
+  result = d3.Add<int128_t>(0, one, 1, 38, 1, false, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_EQ(result.value(), DecimalUtil::MAX_UNSCALED_DECIMAL16 - 8);
 
   // Mod
   overflow = false;
   bool is_nan;
-  ColumnType t3 = ColumnType::CreateDecimalType(38, 20);
-  result = d3.Mod<int128_t>(t1, d3, t3, 38, 20, &is_nan, &overflow);
+  result = d3.Mod<int128_t>(0, d3, 20, 38, 20, false, &is_nan, &overflow);
   EXPECT_TRUE(overflow);
   EXPECT_FALSE(is_nan);
 
   overflow = false;
-  result = d3.Mod<int128_t>(t1, two, t1, 38, 0, &is_nan, &overflow);
+  result = d3.Mod<int128_t>(0, two, 0, 38, 0, false, &is_nan, &overflow);
   EXPECT_FALSE(overflow);
   EXPECT_FALSE(is_nan);
   EXPECT_EQ(result.value(), DecimalUtil::MAX_UNSCALED_DECIMAL16 % 2);
 
-  result = d3.Mod<int128_t>(t1, zero, t2, 38, 1, &is_nan, &overflow);
+  result = d3.Mod<int128_t>(0, zero, 1, 38, 1, false, &is_nan, &overflow);
   EXPECT_TRUE(is_nan);
 }
 
@@ -618,20 +587,20 @@ TEST(DecimalTest, MultiplyScaleOverflow) {
   bool overflow = false;
   Decimal16Value x(1);
   Decimal16Value y(3);
-  ColumnType max_scale = ColumnType::CreateDecimalType(38, 38);
+  int max_scale = 38;
 
   // x = 0.<37 zeroes>1. y = 0.<37 zeroes>3 The result should be 0.<74 
zeroes>3.
   // Since this can't be  represented, the result will truncate to 0.
-  Decimal16Value result = x.Multiply<int128_t>(max_scale, y, max_scale, 38, 
38, &overflow);
+  Decimal16Value result = x.Multiply<int128_t>(max_scale, y, max_scale, 38, 
38, false, &overflow);
   EXPECT_TRUE(result.value() == 0);
   EXPECT_FALSE(overflow);
 
-  ColumnType scale_1 = ColumnType::CreateDecimalType(1, 1);
-  ColumnType scale_37 = ColumnType::CreateDecimalType(38, 37);
+  int scale_1 = 1;
+  int scale_37 = 37;
   // x = 0.<36 zeroes>1, y = 0.3
   // The result should be 0.<37 zeroes>11, which would require scale = 39.
   // The truncated version should 0.<37 zeroes>3.
-  result = x.Multiply<int128_t>(scale_37, y, scale_1, 38, 38, &overflow);
+  result = x.Multiply<int128_t>(scale_37, y, scale_1, 38, 38, false, 
&overflow);
   EXPECT_TRUE(result.value() == 3);
   EXPECT_FALSE(overflow);
 }
@@ -646,7 +615,8 @@ enum Op {
 
 // Implementation of decimal rules. This is handled in the planner in the 
normal
 // execution paths.
-ColumnType GetResultType(const ColumnType& t1, const ColumnType& t2, Op op) {
+ColumnType GetResultType(const ColumnType& t1, const ColumnType& t2, Op op, 
bool v2) {
+  // TODO: Implement V2 result types
   switch (op) {
     case ADD:
     case SUBTRACT:
@@ -658,10 +628,17 @@ ColumnType GetResultType(const ColumnType& t1, const 
ColumnType& t2, Op op) {
       return ColumnType::CreateDecimalType(
           t1.precision + t2.precision, t1.scale + t2.scale);
     case DIVIDE:
-      return ColumnType::CreateDecimalType(
-          min(38,
+      if (v2) {
+        int result_scale =
+            max(ColumnType::MIN_ADJUSTED_SCALE, t1.scale + t2.precision + 1);
+        int result_precision =t1.precision - t1.scale + t2.scale + 
result_scale;
+        return ColumnType::CreateAdjustedDecimalType(result_precision, 
result_scale);
+      } else {
+        return ColumnType::CreateDecimalType(
+          min(ColumnType::MAX_PRECISION,
             t1.precision - t1.scale + t2.scale + max(4, t1.scale + 
t2.precision + 1)),
-          max(4, t1.scale + t2.precision + 1));
+          min(ColumnType::MAX_PRECISION, max(4, t1.scale + t2.precision + 1)));
+      }
     case MOD:
       return ColumnType::CreateDecimalType(
           min(t1.precision - t1.scale, t2.precision - t2.scale) + 
max(t1.scale, t2.scale),
@@ -672,47 +649,65 @@ ColumnType GetResultType(const ColumnType& t1, const 
ColumnType& t2, Op op) {
   }
 }
 
+TEST(DecimalResultTypes, Basic) {
+  ColumnType t1 = ColumnType::CreateDecimalType(38, 10);
+  ColumnType t2 = ColumnType::CreateDecimalType(38, 38);
+  ColumnType t3 = ColumnType::CreateDecimalType(38, 0);
+
+  auto r1 = GetResultType(t1, t2, DIVIDE, true);
+  EXPECT_EQ(r1.precision, 38);
+  EXPECT_EQ(r1.scale, 6);
+
+  auto r2 = GetResultType(t1, t3, DIVIDE, true);
+  EXPECT_EQ(r2.precision, 38);
+  EXPECT_EQ(r2.scale, 10);
+
+  auto r3 = GetResultType(t1, t2, DIVIDE, false);
+  EXPECT_EQ(r3.precision, 38);
+  EXPECT_EQ(r3.scale, 38);
+}
+
 template<typename T>
 void VerifyFuzzyEquals(const T& actual, const ColumnType& t,
-    double expected, bool overflow) {
-  double actual_d = actual.ToDouble(t);
+    double expected, bool overflow, double max_error = MAX_ERROR) {
+  double actual_d = actual.ToDouble(t.scale);
   EXPECT_FALSE(overflow);
-  EXPECT_TRUE(fabs(actual_d - expected) < MAX_ERROR)
+  EXPECT_TRUE(fabs(actual_d - expected) < max_error)
     << actual_d << " != " << expected;
 }
 
 TEST(DecimalArithmetic, Basic) {
   ColumnType t1 = ColumnType::CreateDecimalType(5, 4);
   ColumnType t2 = ColumnType::CreateDecimalType(8, 3);
-  ColumnType t1_plus_2 = GetResultType(t1, t2, ADD);
-  ColumnType t1_times_2 = GetResultType(t1, t2, MULTIPLY);
+  ColumnType t1_plus_2 = GetResultType(t1, t2, ADD, false);
+  ColumnType t1_times_2 = GetResultType(t1, t2, MULTIPLY, false);
 
   Decimal4Value d1(123456789);
   Decimal4Value d2(23456);
   Decimal4Value d3(-23456);
-  double d1_double = d1.ToDouble(t1);
-  double d2_double = d2.ToDouble(t2);
-  double d3_double = d3.ToDouble(t2);
+  double d1_double = d1.ToDouble(t1.scale);
+  double d2_double = d2.ToDouble(t2.scale);
+  double d3_double = d3.ToDouble(t2.scale);
 
   bool overflow = false;
   // TODO: what's the best way to author a bunch of tests like this?
   VerifyFuzzyEquals(d1.Add<int64_t>(
-      t1, d2, t2, t1_plus_2.precision, t1_plus_2.scale, &overflow),
+      t1.scale, d2, t2.scale, t1_plus_2.precision, t1_plus_2.scale, false, 
&overflow),
       t1_plus_2, d1_double + d2_double, overflow);
   VerifyFuzzyEquals(d1.Add<int64_t>(
-      t1, d3, t2, t1_plus_2.precision, t1_plus_2.scale, &overflow),
+      t1.scale, d3, t2.scale, t1_plus_2.precision, t1_plus_2.scale, false, 
&overflow),
       t1_plus_2, d1_double + d3_double, overflow);
   VerifyFuzzyEquals(d1.Subtract<int64_t>(
-      t1, d2, t2, t1_plus_2.precision, t1_plus_2.scale, &overflow),
+      t1.scale, d2, t2.scale, t1_plus_2.precision, t1_plus_2.scale, false, 
&overflow),
       t1_plus_2, d1_double - d2_double, overflow);
   VerifyFuzzyEquals(d1.Subtract<int64_t>(
-      t1, d3, t2, t1_plus_2.precision, t1_plus_2.scale, &overflow),
+      t1.scale, d3, t2.scale, t1_plus_2.precision, t1_plus_2.scale, false, 
&overflow),
       t1_plus_2, d1_double - d3_double, overflow);
   VerifyFuzzyEquals(d1.Multiply<int128_t>(
-      t1, d2, t2, t1_times_2.precision, t1_times_2.scale, &overflow),
+      t1.scale, d2, t2.scale, t1_times_2.precision, t1_times_2.scale, false, 
&overflow),
       t1_times_2, d1_double * d2_double, overflow);
   VerifyFuzzyEquals(d1.Multiply<int64_t>(
-      t1, d3, t2, t1_times_2.precision, t1_times_2.scale, &overflow),
+      t1.scale, d3, t2.scale, t1_times_2.precision, t1_times_2.scale, false, 
&overflow),
       t1_times_2, d1_double * d3_double, overflow);
 }
 
@@ -725,25 +720,27 @@ TEST(DecimalArithmetic, Divide) {
     for (int numerator_s = 0; numerator_s <= numerator_p; ++numerator_s) {
       for (int denominator_p = 1; denominator_p <= 3; ++denominator_p) {
         for (int denominator_s = 0; denominator_s <= denominator_p; 
++denominator_s) {
-          ColumnType t1 = ColumnType::CreateDecimalType(numerator_p, 
numerator_s);
-          ColumnType t2 = ColumnType::CreateDecimalType(denominator_p, 
denominator_s);
-          ColumnType t3 = GetResultType(t1, t2, DIVIDE);
-          bool is_nan = false;
-          bool is_overflow = false;
-          Decimal8Value r = x.Divide<int64_t>(
-              t1, y, t2, t3.precision, t3.scale, &is_nan, &is_overflow);
-          double approx_x = x.ToDouble(t1);
-          double approx_y = y.ToDouble(t2);
-          double approx_r = r.ToDouble(t3);
-          double expected_r = approx_x / approx_y;
-
-          EXPECT_FALSE(is_nan);
-          EXPECT_FALSE(is_overflow);
-          if (fabs(approx_r - expected_r) > MAX_ERROR) {
-            LOG(ERROR) << approx_r << " " << expected_r;
-            LOG(ERROR) << x.ToString(t1) << "/" << y.ToString(t2)
-                       << "=" << r.ToString(t3);
-            EXPECT_TRUE(false);
+          for (int v2: { 0, 1 }) {
+            ColumnType t1 = ColumnType::CreateDecimalType(numerator_p, 
numerator_s);
+            ColumnType t2 = ColumnType::CreateDecimalType(denominator_p, 
denominator_s);
+            ColumnType t3 = GetResultType(t1, t2, DIVIDE, v2);
+            bool is_nan = false;
+            bool is_overflow = false;
+            Decimal8Value r = x.Divide<int64_t>(
+                t1.scale, y, t2.scale, t3.precision, t3.scale, true, &is_nan, 
&is_overflow);
+            double approx_x = x.ToDouble(t1.scale);
+            double approx_y = y.ToDouble(t2.scale);
+            double approx_r = r.ToDouble(t3.scale);
+            double expected_r = approx_x / approx_y;
+
+            EXPECT_FALSE(is_nan);
+            EXPECT_FALSE(is_overflow);
+            if (fabs(approx_r - expected_r) > MAX_ERROR) {
+              LOG(ERROR) << approx_r << " " << expected_r;
+              LOG(ERROR) << x.ToString(t1) << "/" << y.ToString(t2)
+                         << "=" << r.ToString(t3);
+              EXPECT_TRUE(false);
+            }
           }
         }
       }
@@ -752,19 +749,18 @@ TEST(DecimalArithmetic, Divide) {
   // Divide by 0
   bool is_nan = false;
   bool is_overflow = false;
-  Decimal8Value r = x.Divide<int64_t>(ColumnType::CreateDecimalType(10, 0),
-      Decimal4Value(0), ColumnType::CreateDecimalType(2,0), 38, 4, &is_nan, 
&is_overflow);
+  Decimal8Value r = x.Divide<int64_t>(0, Decimal4Value(0), 0, 38, 4, true,
+      &is_nan, &is_overflow);
   EXPECT_TRUE(is_nan) << "Expected NaN, got: " << r;
   EXPECT_FALSE(is_overflow);
 
   // In this case, we are dividing large precision decimals meaning the 
resulting
   // decimal underflows. The resulting type is (38,38).
-  ColumnType t4 = ColumnType::CreateDecimalType(38, 4);
   Decimal16Value x2(53994500);
   Decimal16Value y2(5399450);
   is_nan = false;
   is_overflow = false;
-  x2.Divide<int128_t>(t4, y2, t4, 38, 38, &is_nan, &is_overflow);
+  x2.Divide<int128_t>(4, y2, 4, 38, 38, true, &is_nan, &is_overflow);
   EXPECT_TRUE(is_overflow);
   EXPECT_FALSE(is_nan);
 }
@@ -772,7 +768,7 @@ TEST(DecimalArithmetic, Divide) {
 TEST(DecimalArithmetic, DivideLargeScales) {
   ColumnType t1 = ColumnType::CreateDecimalType(38, 8);
   ColumnType t2 = ColumnType::CreateDecimalType(20, 0);
-  ColumnType t3 = GetResultType(t1, t2, DIVIDE);
+  ColumnType t3 = GetResultType(t1, t2, DIVIDE, false);
   StringParser::ParseResult result;
   const char* data = "319391280635.61476055";
   Decimal16Value x =
@@ -780,15 +776,16 @@ TEST(DecimalArithmetic, DivideLargeScales) {
   Decimal16Value y(10000);
   bool is_nan = false;
   bool is_overflow = false;
-  Decimal16Value r =
-      x.Divide<int128_t>(t1, y, t2, t3.precision, t3.scale, &is_nan, 
&is_overflow);
-  VerifyToString(r, t3, "31939128.06356147605500000000000000000");
+  Decimal16Value r = x.Divide<int128_t>(t1.scale, y, t2.scale, t3.precision, 
t3.scale,
+      true, &is_nan, &is_overflow);
+  VerifyToString(r, t3.precision, t3.scale, 
"31939128.06356147605500000000000000000");
   EXPECT_FALSE(is_nan);
   EXPECT_FALSE(is_overflow);
 
   y = -y;
-  r = x.Divide<int128_t>(t1, y, t2, t3.precision, t3.scale, &is_nan, 
&is_overflow);
-  VerifyToString(r, t3, "-31939128.06356147605500000000000000000");
+  r = x.Divide<int128_t>(t1.scale, y, t2.scale, t3.precision, t3.scale, true,
+      &is_nan, &is_overflow);
+  VerifyToString(r, t3.precision, t3.scale, 
"-31939128.06356147605500000000000000000");
   EXPECT_FALSE(is_nan);
   EXPECT_FALSE(is_overflow);
 }
@@ -826,32 +823,36 @@ TEST(DecimalArithmetic, RandTesting) {
     DecimalValue<int64_t> dec2 = RandDecimal<int64_t>(p2);
     ColumnType t1 = ColumnType::CreateDecimalType(p1, s1);
     ColumnType t2 = ColumnType::CreateDecimalType(p2, s2);
-    double t1_d = dec1.ToDouble(t1);
-    double t2_d = dec2.ToDouble(t2);
+    double t1_d = dec1.ToDouble(s1);
+    double t2_d = dec2.ToDouble(s2);
 
-    ColumnType add_t = GetResultType(t1, t2, ADD);
+    ColumnType add_t = GetResultType(t1, t2, ADD, false);
 
     bool overflow = false;
     VerifyFuzzyEquals(dec1.Add<int64_t>(
-        t1, dec2, t2, add_t.precision, add_t.scale, &overflow),
+        t1.scale, dec2, t2.scale, add_t.precision, add_t.scale, false, 
&overflow),
         add_t, t1_d + t2_d, overflow);
     VerifyFuzzyEquals(dec1.Subtract<int64_t>(
-        t1, dec2, t2, add_t.precision, add_t.scale, &overflow),
+        t1.scale, dec2, t2.scale, add_t.precision, add_t.scale, false, 
&overflow),
         add_t, t1_d - t2_d, overflow);
+    if (overflow) continue;
+
 #if 0
-    TODO: doubles are not precise enough for this
-    ColumnType multiply_t = GetResultType(t1, t2, MULTIPLY);
-    ColumnType divide_t = GetResultType(t1, t2, DIVIDE);
-    // double is too imprecise to generate the right result.
-    // TODO: compare against the ground truth using the multi precision float 
library.
+    // multiply V2 result type not implemented yet
+    ColumnType multiply_t = GetResultType(t1, t2, MULTIPLY, true);
     VerifyFuzzyEquals(dec1.Multiply<int64_t>(
-        t1, dec2, t2, multiply_t.scale), multiply_t, t1_d * t2_d);
-    if (dec2.value() != 0) {
-      VerifyFuzzyEquals(dec1.Divide<int64_t>(
-          t1, dec2, t2, divide_t.scale), divide_t, t1_d / t2_d);
-    }
+        t1.scale, dec2, t2.scale, multiply_t.scale), multiply_t, t1_d * t2_d);
 #endif
-
+    // With rounding, we should be able to get much closer to real values
+    ColumnType divide_t = GetResultType(t1, t2, DIVIDE, true);
+    bool is_nan = false;
+    overflow = false;
+    auto result = dec1.Divide<int128_t>(t1.scale, dec2, t2.scale, 
divide_t.precision,
+        divide_t.scale, true, &is_nan, &overflow);
+    if (!is_nan && !overflow)
+      VerifyFuzzyEquals(result, divide_t, t1_d / t2_d, false,
+          pow(10, divide_t.precision - divide_t.scale - 6));
+    EXPECT_EQ(is_nan, dec2.value() == 0);
     EXPECT_EQ(dec1.Compare(t1.scale, dec2, t2.scale), DoubleCompare(t1_d, 
t2_d));
     EXPECT_TRUE(dec1.Compare(t1.scale, dec1, t1.scale) == 0);
     EXPECT_TRUE(dec2.Compare(t2.scale, dec2, t2.scale) == 0);

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/runtime/decimal-value.h
----------------------------------------------------------------------
diff --git a/be/src/runtime/decimal-value.h b/be/src/runtime/decimal-value.h
index 23c8c6f..88ec2e3 100644
--- a/be/src/runtime/decimal-value.h
+++ b/be/src/runtime/decimal-value.h
@@ -60,10 +60,6 @@ class DecimalValue {
       bool round, bool* overflow);
 
   /// Assigns *result as a decimal.
-  static inline DecimalValue FromInt(const ColumnType& t, int64_t d, bool* 
overflow) {
-    return FromInt(t.precision, t.scale, d, overflow);
-  }
-
   static inline DecimalValue FromInt(int precision, int scale, int64_t d, 
bool* overflow);
 
   /// The overloaded operators assume that this and other have the same scale. 
They are
@@ -102,11 +98,6 @@ class DecimalValue {
   /// Returns a new decimal scaled by from src_type to dst_type.
   /// e.g. If this value was 1100 at scale 3 and the dst_type had scale two, 
the
   /// result would be 110. (In both cases representing the decimal 1.1).
-  inline DecimalValue ScaleTo(const ColumnType& src_type, const ColumnType& 
dst_type,
-      bool* overflow) const {
-    return ScaleTo(src_type.scale, dst_type.scale, dst_type.precision, 
overflow);
-  }
-
   inline DecimalValue ScaleTo(int src_scale, int dst_scale, int dst_precision,
       bool* overflow) const;
 
@@ -119,71 +110,33 @@ class DecimalValue {
   /// not valid.
   /// RESULT_T needs to be larger than T to avoid overflow issues.
   template<typename RESULT_T>
-  inline DecimalValue<RESULT_T> Add(const ColumnType& this_type,
-      const DecimalValue& other, const ColumnType& other_type, int 
result_precision,
-      int result_scale, bool* overflow) const {
-    return Add<RESULT_T>(this_type.scale, other, other_type.scale, 
result_precision,
-        result_scale, overflow);
-  }
-
-  template<typename RESULT_T>
   inline DecimalValue<RESULT_T> Add(int this_scale, const DecimalValue& other,
-      int other_scale, int result_precision, int result_scale, bool* overflow) 
const;
-
-  template<typename RESULT_T>
-  inline DecimalValue<RESULT_T> Subtract(const ColumnType& this_type,
-      const DecimalValue& other, const ColumnType& other_type, int 
result_precision,
-      int result_scale, bool* overflow) const {
-    return Add<RESULT_T>(this_type, -other, other_type, result_precision,
-        result_scale, overflow);
-  }
+      int other_scale, int result_precision, int result_scale, bool round,
+      bool* overflow) const;
 
   template<typename RESULT_T>
   inline DecimalValue<RESULT_T> Subtract(int this_scale, const DecimalValue& 
other,
-      int other_scale, int result_precision, int result_scale, bool* overflow) 
const {
+      int other_scale, int result_precision, int result_scale, bool round,
+      bool* overflow) const {
     return Add<RESULT_T>(this_scale, -other, other_scale, result_precision,
-        result_scale, overflow);
-  }
-
-  template<typename RESULT_T>
-  inline DecimalValue<RESULT_T> Multiply(const ColumnType& this_type,
-      const DecimalValue& other, const ColumnType& other_type, int 
result_precision,
-      int result_scale, bool* overflow) const {
-    return Multiply<RESULT_T>(this_type.scale, other, other_type.scale, 
result_precision,
-        result_scale, overflow);
+        result_scale, round, overflow);
   }
 
   template<typename RESULT_T>
   inline DecimalValue<RESULT_T> Multiply(int this_scale, const DecimalValue& 
other,
-      int other_scale, int result_precision, int result_scale, bool* overflow) 
const;
-
-  /// is_nan is set to true if 'other' is 0. The value returned is undefined.
-  template<typename RESULT_T>
-  inline DecimalValue<RESULT_T> Divide(const ColumnType& this_type,
-      const DecimalValue& other, const ColumnType& other_type, int 
result_precision,
-      int result_scale, bool* is_nan, bool* overflow) const {
-    return Divide<RESULT_T>(this_type.scale, other, other_type.scale, 
result_precision,
-        result_scale, is_nan, overflow);
-  }
-
-  template<typename RESULT_T>
-  inline DecimalValue<RESULT_T> Divide(int this_scale, const DecimalValue& 
other,
-      int other_scale, int result_precision, int result_scale, bool* is_nan,
+      int other_scale, int result_precision, int result_scale, bool round,
       bool* overflow) const;
 
   /// is_nan is set to true if 'other' is 0. The value returned is undefined.
   template<typename RESULT_T>
-  inline DecimalValue<RESULT_T> Mod(const ColumnType& this_type,
-      const DecimalValue& other, const ColumnType& other_type, int 
result_precision,
-      int result_scale, bool* is_nan, bool* overflow) const {
-    return Mod<RESULT_T>(this_type.scale, other, other_type.scale, 
result_precision,
-        result_scale, is_nan, overflow);
-  }
+  inline DecimalValue<RESULT_T> Divide(int this_scale, const DecimalValue& 
other,
+      int other_scale, int result_precision, int result_scale, bool round,
+      bool* is_nan, bool* overflow) const;
 
   template<typename RESULT_T>
   inline DecimalValue<RESULT_T> Mod(int this_scale, const DecimalValue& other,
-      int other_scale, int result_precision, int result_scale, bool* is_nan,
-      bool* overflow) const;
+      int other_scale, int result_precision, int result_scale, bool round,
+      bool* is_nan, bool* overflow) const;
 
   /// Compares this and other. Returns 0 if equal, < 0 if this < other and > 0 
if
   /// this > other.
@@ -215,17 +168,9 @@ class DecimalValue {
   inline T& value() { return value_; }
 
   /// Returns the value of the decimal before the decimal point.
-  inline const T whole_part(const ColumnType& t) const {
-    return whole_part(t.scale);
-  }
-
   inline const T whole_part(int scale) const;
 
   /// Returns the value of the decimal after the decimal point.
-  inline const T fractional_part(const ColumnType& t) const {
-    return fractional_part(t.scale);
-  }
-
   inline const T fractional_part(int scale) const;
 
   /// Returns the value as an integer, setting overflow to true on overflow,
@@ -236,10 +181,6 @@ class DecimalValue {
   inline typename RESULT_T::underlying_type_t ToInt(int scale, bool* overflow) 
const;
 
   /// Returns an approximate double for this decimal.
-  inline double ToDouble(const ColumnType& type) const {
-    return ToDouble(type.scale);
-  }
-
   inline double ToDouble(int scale) const;
 
   inline uint32_t Hash(int seed = 0) const;

Reply via email to