You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by jr...@apache.org on 2017/03/02 21:51:08 UTC

[1/3] incubator-impala git commit: IMPALA-4813: Round on divide and multiply

Repository: incubator-impala
Updated Branches:
  refs/heads/master c46379602 -> 0ad55ba5a


http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/runtime/decimal-value.inline.h
----------------------------------------------------------------------
diff --git a/be/src/runtime/decimal-value.inline.h b/be/src/runtime/decimal-value.inline.h
index 40b1119..5782bfe 100644
--- a/be/src/runtime/decimal-value.inline.h
+++ b/be/src/runtime/decimal-value.inline.h
@@ -110,9 +110,8 @@ inline typename RESULT_T::underlying_type_t DecimalValue<T>::ToInt(int scale,
     // N.B. also - no std::abs for int128_t
     if (abs(remainder) >= divisor >> 1) {
       // Round away from zero.
-      // Note this trick works with both signed and unsigned types
-      const int shift = std::numeric_limits<T>::digits;
-      result += 1 | (result >> shift);
+      // Bias at zero must be corrected by sign of dividend.
+      result += BitUtil::Sign(v);
     }
   }
   *overflow |=
@@ -148,7 +147,7 @@ template<typename T>
 template<typename RESULT_T>
 inline DecimalValue<RESULT_T> DecimalValue<T>::Add(int this_scale,
     const DecimalValue& other, int other_scale, int result_precision, int result_scale,
-    bool* overflow) const {
+    bool round, bool* overflow) const {
   DCHECK_EQ(result_scale, std::max(this_scale, other_scale));
   RESULT_T x = 0;
   RESULT_T y = 0;
@@ -170,7 +169,7 @@ template<typename T>
 template<typename RESULT_T>
 inline DecimalValue<RESULT_T> DecimalValue<T>::Add(int this_scale,
     const DecimalValue& other, int other_scale, int result_precision, int result_scale,
-    bool* overflow) const {
+    bool round, bool* overflow) const {
   DCHECK_EQ(result_scale, std::max(this_scale, other_scale));
   RESULT_T x = 0;
   RESULT_T y = 0;
@@ -193,6 +192,30 @@ inline DecimalValue<RESULT_T> DecimalValue<T>::Add(int this_scale,
 }
 #endif
 
+namespace detail {
+
+// Helper function to scale down over multiplied values back into result type,
+// truncating if round is false or rounding otherwise.
+template<typename T, typename RESULT_T>
+inline RESULT_T ScaleDownAndRound(RESULT_T value, int delta_scale, bool round) {
+  DCHECK_GT(delta_scale, 0);
+  // Multiplier can always be computed in potentially smaller type T
+  T multiplier = DecimalUtil::GetScaleMultiplier<T>(delta_scale);
+  DCHECK(multiplier > 1 && multiplier % 2 == 0);
+  RESULT_T result = value / multiplier;
+  if (round) {
+    RESULT_T remainder = value % multiplier;
+    // In general, shifting down the multiplier is not safe, but we know
+    // here that it is a multiple of two.
+    if (abs(remainder) > (multiplier >> 1)) {
+      // Bias at zero must be corrected by sign of dividend.
+      result += BitUtil::Sign(value);
+    }
+  }
+  return result;
+}
+}
+
 // Use __builtin_mul_overflow on GCC if available.
 // Avoid using on Clang: it requires a function __muloti present in the Clang runtime
 // library but not the GCC runtime library and regresses performance.
@@ -201,7 +224,7 @@ template<typename T>
 template<typename RESULT_T>
 inline DecimalValue<RESULT_T> DecimalValue<T>::Multiply(int this_scale,
     const DecimalValue& other, int other_scale, int result_precision, int result_scale,
-    bool* overflow) const {
+    bool round, bool* overflow) const {
   // In the non-overflow case, we don't need to adjust by the scale since
   // that is already handled by the FE when it computes the result decimal type.
   // e.g. 1.23 * .2 (scale 2, scale 1 respectively) is identical to:
@@ -209,16 +232,10 @@ inline DecimalValue<RESULT_T> DecimalValue<T>::Multiply(int this_scale,
   // The result scale in this case is the sum of the input scales.
   RESULT_T x = value();
   RESULT_T y = other.value();
-  if (x == 0 || y == 0) {
-    // Handle zero to avoid divide by zero in the overflow check below.
-    return DecimalValue<RESULT_T>(0);
-  }
   RESULT_T result = 0;
   if (result_precision == ColumnType::MAX_PRECISION) {
     DCHECK_EQ(sizeof(RESULT_T), 16);
-    // Check overflow
     *overflow |= __builtin_mul_overflow(x, y, &result);
-    *overflow |= abs(result) > DecimalUtil::MAX_UNSCALED_DECIMAL16;
   } else {
     result = x * y;
   }
@@ -227,8 +244,12 @@ inline DecimalValue<RESULT_T> DecimalValue<T>::Multiply(int this_scale,
     // In this case, the required resulting scale is larger than the max we support.
     // We cap the resulting scale to the max supported scale (e.g. truncate) in the FE.
     // TODO: we could also return NULL.
-    DCHECK_GT(delta_scale, 0);
-    result /= DecimalUtil::GetScaleMultiplier<T>(delta_scale);
+    result = detail::ScaleDownAndRound<T, RESULT_T>(result, delta_scale, round);
+
+    // Check overflow again after rounding since +/-1 could cause decimal overflow
+    if (round && result_precision == ColumnType::MAX_PRECISION) {
+      *overflow |= abs(result) > DecimalUtil::MAX_UNSCALED_DECIMAL16;
+    }
   }
   return DecimalValue<RESULT_T>(result);
 }
@@ -237,7 +258,7 @@ template<typename T>
 template<typename RESULT_T>
 DecimalValue<RESULT_T> DecimalValue<T>::Multiply(int this_scale,
     const DecimalValue& other, int other_scale, int result_precision, int result_scale,
-    bool* overflow) const {
+    bool round, bool* overflow) const {
   // In the non-overflow case, we don't need to adjust by the scale since
   // that is already handled by the FE when it computes the result decimal type.
   // e.g. 1.23 * .2 (scale 2, scale 1 respectively) is identical to:
@@ -260,8 +281,11 @@ DecimalValue<RESULT_T> DecimalValue<T>::Multiply(int this_scale,
     // In this case, the required resulting scale is larger than the max we support.
     // We cap the resulting scale to the max supported scale (e.g. truncate) in the FE.
     // TODO: we could also return NULL.
-    DCHECK_GT(delta_scale, 0);
-    result /= DecimalUtil::GetScaleMultiplier<T>(delta_scale);
+    result = detail::ScaleDownAndRound<T, RESULT_T>(result, delta_scale, round);
+    // Check overflow again after rounding since +/-1 could cause decimal overflow
+    if (result_precision == ColumnType::MAX_PRECISION) {
+      *overflow |= abs(result) > DecimalUtil::MAX_UNSCALED_DECIMAL16;
+    }
   }
   return DecimalValue<RESULT_T>(result);
 }
@@ -271,7 +295,7 @@ template<typename T>
 template<typename RESULT_T>
 inline DecimalValue<RESULT_T> DecimalValue<T>::Divide(int this_scale,
     const DecimalValue& other, int other_scale, int result_precision, int result_scale,
-    bool* is_nan, bool* overflow) const {
+    bool round, bool* is_nan, bool* overflow) const {
   DCHECK_GE(result_scale + other_scale, this_scale);
   if (other.value() == 0) {
     // Divide by 0.
@@ -280,20 +304,57 @@ inline DecimalValue<RESULT_T> DecimalValue<T>::Divide(int this_scale,
   }
   // We need to scale x up by the result scale and then do an integer divide.
   // This truncates the result to the output scale.
-  // TODO: implement rounding when decimal_v2=true.
   int scale_by = result_scale + other_scale - this_scale;
   // Use higher precision ints for intermediates to avoid overflows. Divides lead to
   // large numbers very quickly (and get eliminated by the int divide).
   if (sizeof(T) == 16) {
-    int256_t x = DecimalUtil::MultiplyByScale<int256_t>(
-        ConvertToInt256(value()), scale_by);
-    int256_t y = ConvertToInt256(other.value());
+    int128_t x_sp = value();
+    int256_t x = DecimalUtil::MultiplyByScale<int256_t>(ConvertToInt256(x_sp), scale_by);
+    int128_t y_sp = other.value();
+    int256_t y = ConvertToInt256(y_sp);
     int128_t r = ConvertToInt128(x / y, DecimalUtil::MAX_UNSCALED_DECIMAL16, overflow);
+    if (round) {
+      int256_t remainder = x % y;
+      // The following is frought with apparent difficulty, as there is only 1 bit
+      // free in the implementation of int128_t representing our maximum value and
+      // doubling such a value would overflow in two's complement.  However, we
+      // converted y to a 256 bit value, and remainder must be less than y, so there
+      // is plenty of space.  Building a value to DCHECK for this is rather awkward, but
+      // quite obviously 2 * MAX_UNSCALED_DECIMAL16 has plenty of room in 256 bits.
+      // This will need to be fixed if we optimize to get back a 128-bit signed value.
+      if (abs(2 * remainder) >= abs(y)) {
+        // Bias at zero must be corrected by sign of divisor and dividend.
+        r += (BitUtil::Sign(x_sp) ^ BitUtil::Sign(y_sp)) + 1;
+      }
+    }
+    // Check overflow again after rounding since +/-1 could cause decimal overflow
+    if (result_precision == ColumnType::MAX_PRECISION) {
+      *overflow |= abs(r) > DecimalUtil::MAX_UNSCALED_DECIMAL16;
+    }
     return DecimalValue<RESULT_T>(r);
   } else {
+    DCHECK(DecimalUtil::GetScaleMultiplier<RESULT_T>(scale_by) > 0);
     int128_t x = DecimalUtil::MultiplyByScale<RESULT_T>(value(), scale_by);
     int128_t y = other.value();
     int128_t r = x / y;
+    if (round) {
+      int128_t remainder = x % y;
+      // No overflow because doubling the result of 8-byte integers fits in 128 bits
+      DCHECK_LT(sizeof(T), sizeof(remainder));
+      if (abs(2 * remainder) >= abs(y)) {
+        // No bias at zero.  The result scale was chosen such that the smallest non-zero
+        // 'x' divided by the largest 'y' will always produce a non-zero result.
+        // If higher precision were required due to a very large scale, we would be
+        // computing in 256 bits, where getting a zero result is actually a posibility.
+        // In addition, we know the dividend is non-zero, since there was a remainder.
+        // The two conditions combined mean that the result must also be non-zero.
+        DCHECK(r != 0);
+        r += BitUtil::Sign(r);
+      }
+    }
+    DCHECK(abs(r) <= DecimalUtil::MAX_UNSCALED_DECIMAL16 &&
+        (sizeof(RESULT_T) > 8 || abs(r) <= DecimalUtil::MAX_UNSCALED_DECIMAL8) &&
+        (sizeof(RESULT_T) > 4 || abs(r) <= DecimalUtil::MAX_UNSCALED_DECIMAL4));
     return DecimalValue<RESULT_T>(static_cast<RESULT_T>(r));
   }
 }
@@ -302,7 +363,7 @@ template<typename T>
 template<typename RESULT_T>
 inline DecimalValue<RESULT_T> DecimalValue<T>::Mod(int this_scale,
     const DecimalValue& other, int other_scale, int result_precision, int result_scale,
-    bool* is_nan, bool* overflow) const {
+    bool round, bool* is_nan, bool* overflow) const {
   DCHECK_EQ(result_scale, std::max(this_scale, other_scale));
   if (other.value() == 0) {
     // Mod by 0.

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/runtime/types.cc
----------------------------------------------------------------------
diff --git a/be/src/runtime/types.cc b/be/src/runtime/types.cc
index 2cc63ef..2de50e6 100644
--- a/be/src/runtime/types.cc
+++ b/be/src/runtime/types.cc
@@ -30,6 +30,13 @@ using namespace llvm;
 
 namespace impala {
 
+const int ColumnType::MAX_PRECISION;
+const int ColumnType::MAX_SCALE;
+const int ColumnType::MIN_ADJUSTED_SCALE;
+
+const int ColumnType::MAX_DECIMAL4_PRECISION;
+const int ColumnType::MAX_DECIMAL8_PRECISION;
+
 const char* ColumnType::LLVM_CLASS_NAME = "struct.impala::ColumnType";
 
 ColumnType::ColumnType(const std::vector<TTypeNode>& types, int* idx)

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/runtime/types.h
----------------------------------------------------------------------
diff --git a/be/src/runtime/types.h b/be/src/runtime/types.h
index f2db3bd..0657e5f 100644
--- a/be/src/runtime/types.h
+++ b/be/src/runtime/types.h
@@ -84,6 +84,7 @@ struct ColumnType {
   /// Must be kept in sync with FE's max precision/scale.
   static const int MAX_PRECISION = 38;
   static const int MAX_SCALE = MAX_PRECISION;
+  static const int MIN_ADJUSTED_SCALE = 6;
 
   /// The maximum precision representable by a 4-byte decimal (Decimal4Value)
   static const int MAX_DECIMAL4_PRECISION = 9;
@@ -140,6 +141,17 @@ struct ColumnType {
     return ret;
   }
 
+  // Matches the results of createAdjustedDecimalType in front-end code.
+  static ColumnType CreateAdjustedDecimalType(int precision, int scale) {
+    if (precision > MAX_PRECISION) {
+      int min_scale = std::min(scale, MIN_ADJUSTED_SCALE);
+      int delta = precision - MAX_PRECISION;
+      precision = MAX_PRECISION;
+      scale = std::max(scale - delta, min_scale);
+    }
+    return CreateDecimalType(precision, scale);
+  }
+
   static ColumnType FromThrift(const TColumnType& t) {
     int idx = 0;
     ColumnType result(t.types, &idx);

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/util/bit-util-test.cc
----------------------------------------------------------------------
diff --git a/be/src/util/bit-util-test.cc b/be/src/util/bit-util-test.cc
index 663f10f..2559d18 100644
--- a/be/src/util/bit-util-test.cc
+++ b/be/src/util/bit-util-test.cc
@@ -29,9 +29,37 @@
 #include "util/cpu-info.h"
 
 #include "common/names.h"
+#include "runtime/multi-precision.h"
 
 namespace impala {
 
+TEST(BitUtil, UnsignedWidth) {
+  EXPECT_EQ(BitUtil::UnsignedWidth<signed char>(), 7);
+  EXPECT_EQ(BitUtil::UnsignedWidth<unsigned char>(), 8);
+  EXPECT_EQ(BitUtil::UnsignedWidth<volatile long long>(), 63);
+  EXPECT_EQ(BitUtil::UnsignedWidth<unsigned long long&>(), 64);
+  EXPECT_EQ(BitUtil::UnsignedWidth<const int128_t&>(), 127);
+  EXPECT_EQ(BitUtil::UnsignedWidth<const volatile unsigned __int128&>(), 128);
+}
+
+TEST(BitUtil, Sign) {
+  EXPECT_EQ(BitUtil::Sign<int>(0), 1);
+  EXPECT_EQ(BitUtil::Sign<int>(1), 1);
+  EXPECT_EQ(BitUtil::Sign<int>(-1), -1);
+  EXPECT_EQ(BitUtil::Sign<int>(200), 1);
+  EXPECT_EQ(BitUtil::Sign<int>(-200), -1);
+  EXPECT_EQ(BitUtil::Sign<unsigned int>(0), 1);
+  EXPECT_EQ(BitUtil::Sign<unsigned int>(1), 1);
+  EXPECT_EQ(BitUtil::Sign<unsigned int>(-1U), 1);
+  EXPECT_EQ(BitUtil::Sign<unsigned int>(200), 1);
+  EXPECT_EQ(BitUtil::Sign<unsigned int>(-200), 1);
+  EXPECT_EQ(BitUtil::Sign<int128_t>(0), 1);
+  EXPECT_EQ(BitUtil::Sign<int128_t>(1), 1);
+  EXPECT_EQ(BitUtil::Sign<int128_t>(-1), -1);
+  EXPECT_EQ(BitUtil::Sign<int128_t>(200), 1);
+  EXPECT_EQ(BitUtil::Sign<int128_t>(-200), -1);
+}
+
 TEST(BitUtil, Ceil) {
   EXPECT_EQ(BitUtil::Ceil(0, 1), 0);
   EXPECT_EQ(BitUtil::Ceil(1, 1), 1);

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/util/bit-util.h
----------------------------------------------------------------------
diff --git a/be/src/util/bit-util.h b/be/src/util/bit-util.h
index bc9bcaf..571f1ae 100644
--- a/be/src/util/bit-util.h
+++ b/be/src/util/bit-util.h
@@ -26,8 +26,8 @@
 #endif
 
 #include <climits>
-
 #include <limits>
+#include <typeinfo>
 
 #include <boost/type_traits/make_unsigned.hpp>
 
@@ -43,6 +43,29 @@ using boost::make_unsigned;
 /// TODO: is this in boost or something else like that?
 class BitUtil {
  public:
+
+  /// Returns the width of the integer portion of the type, not counting the sign bit.
+  /// Not safe for use with unknown or non-native types, so make it undefined
+  template<typename T, typename CVR_REMOVED = typename std::decay<T>::type,
+      typename std::enable_if<std::is_integral<CVR_REMOVED>{} ||
+                              std::is_same<CVR_REMOVED, unsigned __int128>{} ||
+                              std::is_same<CVR_REMOVED, __int128>{}, int>::type = 0>
+  constexpr static inline int UnsignedWidth() {
+    return std::is_integral<CVR_REMOVED>::value ?
+        std::numeric_limits<CVR_REMOVED>::digits :
+        std::is_same<CVR_REMOVED, unsigned __int128>::value ? 128 :
+        std::is_same<CVR_REMOVED, __int128>::value ? 127 : -1;
+  }
+
+  /// Return an integer signifying the sign of the value, returning +1 for
+  /// positive integers (and zero), -1 for negative integers.
+  /// The extra shift is to silence GCC warnings about full width shift on
+  /// unsigned types.  It compiles out in optimized builds into the expected increment
+  template<typename T>
+  constexpr static inline T Sign(T value) {
+    return 1 | ((value >> (UnsignedWidth<T>() - 1)) >> 1);
+  }
+
   /// Returns the ceil of value/divisor
   constexpr static inline int64_t Ceil(int64_t value, int64_t divisor) {
     return value / divisor + (value % divisor != 0);

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/be/src/util/string-parser.h
----------------------------------------------------------------------
diff --git a/be/src/util/string-parser.h b/be/src/util/string-parser.h
index a123924..62e7dcc 100644
--- a/be/src/util/string-parser.h
+++ b/be/src/util/string-parser.h
@@ -100,12 +100,6 @@ class StringParser {
   /// On overflow or invalid values, the return value is undefined.
   /// On underflow, the truncated value is returned.
   template <typename T>
-  static inline DecimalValue<T> StringToDecimal(const uint8_t* s, int len,
-      const ColumnType& type, StringParser::ParseResult* result) {
-    return StringToDecimal<T>(reinterpret_cast<const char*>(s), len, type, result);
-  }
-
-  template <typename T>
   static inline DecimalValue<T> StringToDecimal(const char* s, int len,
       const ColumnType& type, StringParser::ParseResult* result) {
     return StringToDecimal<T>(s, len, type.precision, type.scale, result);

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/c87ab35a/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test b/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test
index 1dff5f1..b1c62ec 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/decimal-exprs.test
@@ -19,10 +19,10 @@ DECIMAL, DECIMAL, DECIMAL, DECIMAL, DECIMAL
 set decimal_v2=true;
 select d1 / d2, d2 / d1, d3 / d4, d5 / d3, d3 / d5 from decimal_tbl;
 ---- RESULTS
-0.55535553555,1.8006482982,10.000000,10000.08918100081154710738507,0.000099999108197945064
-21.12612612612,0.0473347547,100.000000,0.25442100231523112106860,3.930493123209169054441
-37.07207207207,0.0269744835,1000.000000,0.09088200082702620752593,11.003278877005347593582
-37.07207207207,0.0269744835,10000.000000,0.00008100000073710000670,12345.678900000000000000000
+0.55535553555,1.8006482982,10.000000,10000.08918100081154710738508,0.000099999108197945065
+21.12612612613,0.0473347548,100.000000,0.25442100231523112106860,3.930493123209169054441
+37.07207207207,0.0269744836,1000.000000,0.09088200082702620752594,11.003278877005347593583
+37.07207207207,0.0269744836,10000.000000,0.00008100000073710000671,12345.678900000000000000000
 398.92492492492,0.0025067373,100000.000000,0.00006309009057411982422,15850.349728459731155875669
 ---- TYPES
 DECIMAL, DECIMAL, DECIMAL, DECIMAL, DECIMAL
@@ -114,14 +114,14 @@ select l_tax, avg(cast(l_extendedprice as decimal(38,10))), avg(l_extendedprice)
 from tpch_parquet.lineitem group by l_tax order by 1;
 ---- RESULTS
 0.00,38241.5984613546,38241.598461
-0.01,38283.5417664599,38283.541766
+0.01,38283.5417664600,38283.541766
 0.02,38250.4873094187,38250.487309
 0.03,38259.2810374789,38259.281037
 0.04,38247.1967454731,38247.196745
 0.05,38234.8480874721,38234.848087
 0.06,38246.4342924027,38246.434292
-0.07,38281.1963710003,38281.196371
-0.08,38251.6233675941,38251.623367
+0.07,38281.1963710004,38281.196371
+0.08,38251.6233675942,38251.623368
 ---- TYPES
 DECIMAL,DECIMAL,DECIMAL
 ====
@@ -147,7 +147,7 @@ group by l_tax having a > 38247.190 order by 1;
 ---- RESULTS
 38247.196745
 38250.487309
-38251.623367
+38251.623368
 38259.281037
 38281.196371
 38283.541766


[3/3] incubator-impala git commit: IMPALA-3402: [DOCS] Remove/reword all CDH 4 references

Posted by jr...@apache.org.
IMPALA-3402: [DOCS] Remove/reword all CDH 4 references

Along the way, remove nearby references to CDH 5
and especially the CDH version numbers in the
'Fixed Issues' titles. The fixed issues titles
are not amenable to the keydef/keyref substitution
technique because they are all 3-part numbers
like Impala 2.2.1 that don't have substitution
variables defined for them.

Change-Id: I9ffb400a244930134705b0f0039087506f5e70d3
Reviewed-on: http://gerrit.cloudera.org:8080/6146
Reviewed-by: John Russell <jr...@cloudera.com>
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/0ad55ba5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/0ad55ba5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/0ad55ba5

Branch: refs/heads/master
Commit: 0ad55ba5a95ccdb9c514fa0c98996bd2ecbe606e
Parents: c87ab35
Author: John Russell <jr...@cloudera.com>
Authored: Fri Feb 24 15:57:13 2017 -0800
Committer: Impala Public Jenkins <im...@gerrit.cloudera.org>
Committed: Thu Mar 2 21:05:01 2017 +0000

----------------------------------------------------------------------
 docs/topics/impala_avro.xml                 |  5 +-
 docs/topics/impala_char.xml                 |  3 +-
 docs/topics/impala_decimal.xml              |  4 --
 docs/topics/impala_fixed_issues.xml         | 84 ++++++++++--------------
 docs/topics/impala_incompatible_changes.xml |  7 --
 docs/topics/impala_install.xml              |  9 +--
 docs/topics/impala_new_features.xml         | 15 +----
 docs/topics/impala_noncm_installation.xml   |  6 +-
 docs/topics/impala_parquet.xml              |  4 +-
 docs/topics/impala_perf_resources.xml       |  4 +-
 docs/topics/impala_scalability.xml          | 14 ++--
 docs/topics/impala_subqueries.xml           |  2 +-
 docs/topics/impala_txtfile.xml              |  4 +-
 docs/topics/impala_udf.xml                  | 18 +++--
 14 files changed, 68 insertions(+), 111 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_avro.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_avro.xml b/docs/topics/impala_avro.xml
index 852cf8c..3ec7b99 100644
--- a/docs/topics/impala_avro.xml
+++ b/docs/topics/impala_avro.xml
@@ -216,8 +216,7 @@ for this information.
         <li>
           The <codeph>DECIMAL</codeph> type is defined in Avro as a <codeph>BYTE</codeph> type with the
           <codeph>logicalType</codeph> property set to <codeph>"decimal"</codeph> and a specified precision and
-          scale. Use <codeph>DECIMAL</codeph> in Avro tables only under CDH 5. The infrastructure and components
-          under CDH 4 do not have reliable <codeph>DECIMAL</codeph> support.
+          scale.
         </li>
 
         <li>
@@ -255,7 +254,7 @@ for this information.
           An Impala <codeph>TIMESTAMP</codeph> column definition maps to an Avro <codeph>STRING</codeph> and is presented as a <codeph>STRING</codeph>
           in the reconciled schema, because Avro has no binary <codeph>TIMESTAMP</codeph> representation.
           As a result, no Avro table can have a <codeph>TIMESTAMP</codeph> column; this restriction is the same as
-          in earlier CDH and Impala releases.
+          in earlier Impala releases.
         </li>
         </ul>
       </p>

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_char.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_char.xml b/docs/topics/impala_char.xml
index dc8ad5a..9204812 100644
--- a/docs/topics/impala_char.xml
+++ b/docs/topics/impala_char.xml
@@ -125,8 +125,7 @@ under the License.
     <p conref="../shared/impala_common.xml#common/compatibility_blurb"/>
 
     <p>
-      This type is available using Impala 2.0 or higher under CDH 4, or with Impala on CDH 5.2 or higher. There are
-      no compatibility issues with other components when exchanging data files or running Impala on CDH 4.
+      This type is available using <keyword keyref="impala20_full"/> or higher.
     </p>
 
     <p>

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_decimal.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_decimal.xml b/docs/topics/impala_decimal.xml
index 36b149d..80e8130 100644
--- a/docs/topics/impala_decimal.xml
+++ b/docs/topics/impala_decimal.xml
@@ -717,10 +717,6 @@ Expression '1' (type: INT) would need to be cast to DECIMAL(9,0) for column 'x'
         depending on the precision specified for the <codeph>DECIMAL</codeph> column.
       </li>
 
-      <li>
-        Parquet files containing <codeph>DECIMAL</codeph> columns are not expected to be readable under CDH 4. See
-        the <b>Compatibility</b> section for details.
-      </li>
     </ul>
 
     <p>

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_fixed_issues.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_fixed_issues.xml b/docs/topics/impala_fixed_issues.xml
index a1f4de0..a063ff3 100644
--- a/docs/topics/impala_fixed_issues.xml
+++ b/docs/topics/impala_fixed_issues.xml
@@ -2200,7 +2200,7 @@ ce601ec : Enable using isilon as the underlying filesystem.
 
   <concept rev="2.2.0" id="fixed_issues_220">
 
-    <title>Issues Fixed in the 2.2.0 Release / CDH 5.4.0</title>
+    <title>Issues Fixed in <keyword keyref="impala22_full"/></title>
 
     <conbody>
 
@@ -2210,13 +2210,6 @@ ce601ec : Enable using isilon as the underlying filesystem.
 
       <p>
         For the full list of fixed issues in Impala 2.2.0, including over 40 critical issues, see
-<!--
-  In maintenance releases, the CDH fixed issues topics did include a nice compact list of Impala JIRAs.
-  But now in 5.4, it's back to lengthy descriptions for fixed issues and the Impala ones don't have a
-  complete compact list anywhere in the docs. So returning to the practice of linking to the list in
-  the JIRA system like was done before.
--->
-        <!-- <xref audience="standalone" href="http://www.cloudera.com/documentation/enterprise/latest/topics/cdh_rn_fixed_in_540.html" format="html" scope="external">the CDH 5.4.0 release notes</xref><xref audience="integrated" href="cdh_rn_fixed_in_540.xml"/>. -->
         <xref href="https://issues.cloudera.org/secure/IssueNavigator.jspa?reset=true&amp;jqlQuery=project%3Dimpala+and+fixVersion%3D%22Impala+2.2%22+and+resolution%3D%22Fixed%22" format="html" scope="external">
         this report in the JIRA system</xref>.
       </p>
@@ -2422,12 +2415,12 @@ IMPALA-1607
 
   <concept rev="2.1.7" id="fixed_issues_217">
 
-    <title>Issues Fixed in the 2.1.7 Release / CDH 5.3.9</title>
+    <title>Issues Fixed in Impala 2.1.7</title>
 
     <conbody>
 
       <p>
-        This section lists the most significant Impala issues fixed in Impala 2.1.7 for CDH 5.3.9.
+        This section lists the most significant Impala issues fixed in Impala 2.1.7.
       </p>
 
       <p> For the full list of Impala fixed issues in this release, see <xref
@@ -2520,12 +2513,12 @@ e591cf4 IMPALA-2141: UnionNode::GetNext() doesn't check for query errors
 
   <concept rev="2.1.6" id="fixed_issues_216">
 
-    <title>Issues Fixed in the 2.1.6 Release / CDH 5.3.8</title>
+    <title>Issues Fixed in Impala 2.1.6</title>
 
     <conbody>
 
       <p>
-        This section lists the most significant Impala issues fixed in Impala 2.1.6 for CDH 5.3.8.
+        This section lists the most significant Impala issues fixed in Impala 2.1.6.
       </p>
 
       <p> For the full list of Impala fixed issues in this release, see <!-- Don't think we have quite the right combination of conditional options to make this reference be a web link in Impala PDF and a normal xref in Release Notes PDF. -->
@@ -2608,12 +2601,12 @@ e591cf4 IMPALA-2141: UnionNode::GetNext() doesn't check for query errors
 
   <concept rev="2.1.5" id="fixed_issues_215">
 
-    <title>Issues Fixed in the 2.1.5 Release / CDH 5.3.6</title>
+    <title>Issues Fixed in Impala 2.1.5</title>
 
     <conbody>
 
       <p>
-        This section lists the most significant Impala issues fixed in Impala 2.1.5 for CDH 5.3.6.
+        This section lists the most significant Impala issues fixed in Impala 2.1.5.
       </p>
 
       <p> For the full list of Impala fixed issues in this release, see <!-- Don't think we have quite the right combination of conditional options to make this reference be a web link in Impala PDF and a normal xref in Release Notes PDF. -->
@@ -2650,17 +2643,17 @@ e591cf4 IMPALA-2141: UnionNode::GetNext() doesn't check for query errors
 
   <concept rev="2.1.4" id="fixed_issues_214">
 
-    <title>Issues Fixed in the 2.1.4 Release /  CDH 5.3.4</title>
+    <title>Issues Fixed in Impala 2.1.4</title>
 
     <conbody>
 
       <p>
-        This section lists the most significant Impala issues fixed in Impala 2.1.4 for CDH 5.3.4.
+        This section lists the most significant Impala issues fixed in Impala 2.1.4.
         <ph conref="../shared/impala_common.xml#common/impala_214_redux"/>
       </p>
 
-      <p> For the full list of Impala fixed issues in Impala 2.1.4 for CDH
-        5.3.4, see <xref audience="standalone"
+      <p> For the full list of Impala fixed issues in Impala 2.1.4,
+        see <xref audience="standalone"
           href="http://www.cloudera.com/documentation/enterprise/latest/topics/cdh_rn_fixed_in_534.html"
           format="html" scope="external">the CDH 5.3.4 release notes</xref><xref
           href="cdh_rn_fixed_in_53.xml#fixed_issues_534" audience="integrated"
@@ -2796,7 +2789,7 @@ c132c75 IMPALA-1808: AnalyticEvalNode cannot handle partition/order by exprs wit
 
   <concept rev="2.1.3" id="fixed_issues_213">
 
-    <title>Issues Fixed in the 2.1.3 Release / CDH 5.3.3</title>
+    <title>Issues Fixed in Impala 2.1.3</title>
 
     <conbody>
 
@@ -2940,7 +2933,7 @@ c132c75 IMPALA-1808: AnalyticEvalNode cannot handle partition/order by exprs wit
 
   <concept rev="2.1.2" id="fixed_issues_212">
 
-    <title>Issues Fixed in the 2.1.2 Release / CDH 5.3.2</title>
+    <title>Issues Fixed in Impala 2.1.2</title>
 
     <conbody>
 
@@ -3010,7 +3003,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API - also in 5.2.4 /
 
   <concept rev="2.1.1" id="fixed_issues_211">
 
-    <title>Issues Fixed in the 2.1.1 Release / CDH 5.3.1</title>
+    <title>Issues Fixed in Impala 2.1.1</title>
 
     <conbody>
 
@@ -3073,7 +3066,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API - also in 5.2.4 /
 
   <concept rev="2.1.0" id="fixed_issues_210">
 
-    <title>Issues Fixed in the 2.1.0 Release / CDH 5.3.0</title>
+    <title>Issues Fixed in Impala 2.1.0</title>
 
     <conbody>
 
@@ -3193,7 +3186,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API - also in 5.2.4 /
 
   <concept rev="2.0.5" id="fixed_issues_205">
 
-    <title>Issues Fixed in the 2.0.5 Release / CDH 5.2.6</title>
+    <title>Issues Fixed in Impala 2.0.5</title>
 
     <conbody>
 
@@ -3210,7 +3203,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API - also in 5.2.4 /
 
   <concept rev="2.0.4" id="fixed_issues_204">
 
-    <title>Issues Fixed in the 2.0.4 Release / CDH 5.2.5</title>
+    <title>Issues Fixed in Impala 2.0.4</title>
 
     <conbody>
 
@@ -3279,7 +3272,7 @@ db3362f IMPALA-1801: external-data-source-executor leaking global jni refs
 
   <concept rev="2.0.3" id="fixed_issues_203">
 
-    <title>Issues Fixed in the 2.0.3 Release / CDH 5.2.4</title>
+    <title>Issues Fixed in Impala 2.0.3</title>
 
     <conbody>
 
@@ -3338,7 +3331,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="2.0.2" id="fixed_issues_202">
 
-    <title>Issues Fixed in the 2.0.2 Release / CDH 5.2.3</title>
+    <title>Issues Fixed in Impala 2.0.2</title>
 
     <conbody>
 
@@ -3357,8 +3350,6 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
       <p outputclass="toc inpage"/>
     </conbody>
 
-<!-- These fixed JIRAs are copied from from impala_fixed_issues.xml. Going forward, the content in this file is the baseline for future changes. -->
-
     <concept id="IMPALA-1453">
 
       <title>GROUP BY on STRING column produces inconsistent results</title>
@@ -3467,7 +3458,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="2.0.1" id="fixed_issues_201">
 
-    <title>Issues Fixed in the 2.0.1 Release / CDH 5.2.1</title>
+    <title>Issues Fixed in Impala 2.0.1</title>
 
     <conbody>
 
@@ -3515,7 +3506,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="2.0.0" id="fixed_issues_200">
 
-    <title>Issues Fixed in the 2.0.0 Release / CDH 5.2.0</title>
+    <title>Issues Fixed in Impala 2.0.0</title>
 
     <conbody>
 
@@ -3845,12 +3836,11 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
   </concept>
 
   <concept rev="1.4.4" id="fixed_issues_144">
-  <title>Issues Fixed in the 1.4.4 Release / CDH 5.1.5</title>
+  <title>Issues Fixed in Impala 1.4.4</title>
     <conbody>
       <p>
         For the list of fixed issues, see
-        <xref href="http://www.cloudera.com/documentation/enterprise/release-notes/topics/cdh_rn_fixed_in_51.html" scope="external" format="html">Issues Fixed in CDH 5.1.5</xref>
-        in the <cite>CDH 5 Release Notes</cite>.
+        <xref href="http://www.cloudera.com/documentation/enterprise/release-notes/topics/cdh_rn_fixed_in_51.html" scope="external" format="html">Issues Fixed in CDH 5.1.5</xref>.
       </p>
 
       <note conref="../shared/impala_common.xml#common/only_cdh5_144"/>
@@ -3860,7 +3850,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="1.4.3" id="fixed_issues_143">
 
-    <title>Issues Fixed in the 1.4.3 Release / CDH 5.1.4</title>
+    <title>Issues Fixed in Impala 1.4.3</title>
 
     <conbody>
 
@@ -3876,7 +3866,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="1.4.2" id="fixed_issues_142">
 
-    <title>Issues Fixed in the 1.4.2 Release / CDH 5.1.3</title>
+    <title>Issues Fixed in Impala 1.4.2</title>
 
     <conbody>
 
@@ -3898,7 +3888,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="1.4.1" id="fixed_issues_141">
 
-    <title>Issues Fixed in the 1.4.1 Release / CDH 5.1.2</title>
+    <title>Issues Fixed in Impala 1.4.1</title>
 
     <conbody>
 
@@ -4065,7 +4055,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="1.4.0" id="fixed_issues_140">
 
-    <title>Issues Fixed in the 1.4.0 Release / CDH 5.1.0</title>
+    <title>Issues Fixed in Impala 1.4.0</title>
 
     <conbody>
 
@@ -4328,7 +4318,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="1.3.3" id="fixed_issues_133">
 
-    <title>Issues Fixed in the 1.3.3 Release / CDH 5.0.5</title>
+    <title>Issues Fixed in Impala 1.3.3</title>
 
     <conbody>
 
@@ -4345,7 +4335,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="1.3.2" id="fixed_issues_132">
 
-    <title>Issues Fixed in the 1.3.2 Release / CDH 5.0.4</title>
+    <title>Issues Fixed in Impala 1.3.2</title>
 
     <conbody>
 
@@ -4383,8 +4373,8 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
         </p>
 
         <p>
-          <b>Workaround:</b> On CDH 5.0.x, upgrade to CDH 5.0.4 with Impala 1.3.2, where this issue is fixed. In
-          Impala 1.3.0 or 1.3.1 on CDH 5.0.x, do not use HDFS caching for Impala data files in Impala internal or
+          <b>Workaround:</b> Upgrade to CDH 5.0.4 with Impala 1.3.2, where this issue is fixed. In
+          Impala 1.3.0 or 1.3.1, do not use HDFS caching for Impala data files in Impala internal or
           external tables. If some of these data files are cached (for example because they are used by other
           components that take advantage of HDFS caching), set the query option
           <codeph>DISABLE_CACHED_READS=true</codeph>. To set that option for all Impala queries across all
@@ -4394,8 +4384,8 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
         </p>
 
         <p>
-          <b>Resolution:</b> This issue is fixed in Impala 1.3.2 for CDH 5.0.4. The addition of HDFS caching
-          support in Impala 1.4 means that this issue does not apply to any new level of Impala on CDH 5.
+          <b>Resolution:</b> This issue is fixed in Impala 1.3.2. The addition of HDFS caching
+          support in Impala 1.4 means that this issue does not apply to any new level of Impala.
         </p>
       </conbody>
     </concept>
@@ -4403,7 +4393,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="1.3.1" id="fixed_issues_131">
 
-    <title>Issues Fixed in the 1.3.1 Release / CDH 5.0.3</title>
+    <title>Issues Fixed in Impala 1.3.1</title>
 
     <conbody>
 
@@ -4414,9 +4404,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
       <p>
         For the full list of fixed issues in Impala 1.3.1, see
         <xref href="https://issues.cloudera.org/secure/IssueNavigator.jspa?reset=true&amp;jqlQuery=project%3Dimpala+and+fixVersion%3D%22Impala+1.3.1%22+and+resolution%3D%22Fixed%22" format="html" scope="external">
-        this report in the JIRA system</xref>. Because 1.3.1 is the first 1.3.x release for CDH 4, if you are on
-        CDH 4, also consult <xref href="impala_fixed_issues.xml#fixed_issues_130"/>.
-<!--      <xref href="https://issues.cloudera.org/secure/IssueNavigator.jspa?reset=true&amp;jqlQuery=project%3Dimpala+and+fixVersion%3D%22Impala+1.3%22+and+resolution%3D%22Fixed%22" format="html" scope="external">list of issues fixed in 1.3.0</xref>. -->
+        this report in the JIRA system</xref>.
       </p>
 
       <p outputclass="toc inpage"/>
@@ -4642,7 +4630,7 @@ IMPALA-1120: Fetch column statistics using Hive 0.13 bulk API    this one fix th
 
   <concept rev="1.3.0" id="fixed_issues_130">
 
-    <title>Issues Fixed in the 1.3.0 Release / CDH 5.0.0</title>
+    <title>Issues Fixed in Impala 1.3.0</title>
 
     <conbody>
 

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_incompatible_changes.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_incompatible_changes.xml b/docs/topics/impala_incompatible_changes.xml
index 897d973..c10555c 100644
--- a/docs/topics/impala_incompatible_changes.xml
+++ b/docs/topics/impala_incompatible_changes.xml
@@ -1226,7 +1226,6 @@ select * from `cross`;</codeblock>
         to Impala 1.2.x in general.
       </p>
 
-<!-- <note conref="common.xml#common/cdh4_cdh5_upgrade"/> -->
     </conbody>
   </concept>
 
@@ -1251,12 +1250,6 @@ select * from `cross`;</codeblock>
       </ul>
 
       <p>
-        Impala 1.2.1 goes along with CDH 4.5 and Cloudera Manager 4.8. If you used the beta version Impala 1.2.0
-        that came with the beta of CDH 5, Impala 1.2.1 includes all the features of Impala 1.2.0 except for
-        resource management, which relies on the YARN framework from CDH 5.
-      </p>
-
-      <p>
         The new <cmdname>catalogd</cmdname> service might require changes to any user-written scripts that stop,
         start, or restart Impala services, install or upgrade Impala packages, or issue <codeph>REFRESH</codeph> or
         <codeph>INVALIDATE METADATA</codeph> statements:

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_install.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_install.xml b/docs/topics/impala_install.xml
index adb502c..24d37ab 100644
--- a/docs/topics/impala_install.xml
+++ b/docs/topics/impala_install.xml
@@ -41,17 +41,10 @@ under the License.
       <indexterm audience="hidden">impalad</indexterm>
       <indexterm audience="hidden">impala-shell</indexterm>
       <indexterm audience="hidden">statestored</indexterm>
-      Impala is an open-source add-on to the Cloudera Enterprise Core that returns rapid responses to
+      Impala is an open-source project that returns rapid responses to
       queries.
     </p>
 
-    <note>
-      <p>
-        Under CDH 5, Impala is included as part of the CDH installation and no separate steps are needed.
-        <ph audience="standalone">Therefore, the instruction steps in this section apply to CDH 4 only.</ph>
-      </p>
-    </note>
-
     <p outputclass="toc inpage"/>
   </conbody>
 

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_new_features.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_new_features.xml b/docs/topics/impala_new_features.xml
index 4a237f7..ed908b6 100644
--- a/docs/topics/impala_new_features.xml
+++ b/docs/topics/impala_new_features.xml
@@ -3060,8 +3060,9 @@ under the License.
     <conbody>
 
       <note>
-        Impala 1.2.1 works with CDH 4. Its feature set is a superset of features in the Impala 1.2.0 beta, with the
-        exception of resource management, which relies on CDH 5.
+        The Impala 1.2.1 feature set is a superset of features in the Impala 1.2.0 beta, with the
+        exception of resource management, which relies on resource management infrastructure in the
+        underlying Hadoop distribution.
       </note>
 
       <p>
@@ -3797,12 +3798,6 @@ under the License.
         </li>
       </ul>
 
-      <p>
-        In this version, both CDH 4.1 and 4.2 are supported, but due to performance improvements added, we highly
-        recommend you use CDH 4.2 or higher to see the full benefit. If you are using Cloudera Manager, version 4.5
-        is required.
-      </p>
-
     </conbody>
 
   </concept>
@@ -3836,10 +3831,6 @@ under the License.
         </li>
 
         <li>
-          Cloudera Manager 4.5 and CDH 4.2 support Impala 0.6.
-        </li>
-
-        <li>
           Support for the RCFile file format. For more information on file formats, see
           <xref href="impala_file_formats.xml#file_formats">Understanding File Formats</xref>.
         </li>

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_noncm_installation.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_noncm_installation.xml b/docs/topics/impala_noncm_installation.xml
index 518f917..ca2ba06 100644
--- a/docs/topics/impala_noncm_installation.xml
+++ b/docs/topics/impala_noncm_installation.xml
@@ -75,8 +75,8 @@ under the License.
           described in the CDH Installation Guide).
         </p>
         <p>
-          <ph rev="upstream">Cloudera</ph> recommends setting up a Hive metastore service rather than connecting directly to the metastore
-          database; this configuration is required when running Impala under CDH 4.1. Make sure the
+          Whenever practical, set up a Hive metastore service rather than connecting directly to the metastore
+          database. Make sure the
           <filepath>/etc/impala/conf/hive-site.xml</filepath> file contains the following setting, substituting the
           appropriate hostname for <varname>metastore_server_host</varname>:
         </p>
@@ -106,7 +106,7 @@ $</codeblock>
 
       <li>
         Confirm that your package management command is aware of the Impala repository settings, as described in
-        <xref href="impala_prereqs.xml#prereqs"/>. (For CDH 4, this is a different repository than for CDH.) You
+        <xref href="impala_prereqs.xml#prereqs"/>. You
         might need to download a repo or list file into a system directory underneath <filepath>/etc</filepath>.
       </li>
 

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_parquet.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_parquet.xml b/docs/topics/impala_parquet.xml
index 0a0f4f5..e4f8a7f 100644
--- a/docs/topics/impala_parquet.xml
+++ b/docs/topics/impala_parquet.xml
@@ -714,7 +714,7 @@ Returned 1 row(s) in 13.35s
     <conbody>
 
       <p>
-        Starting in CDH 4.5, you can read and write Parquet data files from other CDH components.
+        You can read and write Parquet data files from other CDH components.
         <ph audience="integrated">See <xref href="cdh_ig_parquet.xml#parquet_format"/> for details.</ph>
       </p>
 
@@ -728,7 +728,7 @@ Returned 1 row(s) in 13.35s
 
       <p>
         Previously, it was not possible to create Parquet data through Impala and reuse that table within Hive. Now
-        that Parquet support is available for Hive in CDH 4.5, reusing existing Impala Parquet data files in Hive
+        that Parquet support is available for Hive, reusing existing Impala Parquet data files in Hive
         requires updating the table metadata. Use the following command if you are already running Impala 1.1.1 or
         higher:
       </p>

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_perf_resources.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_perf_resources.xml b/docs/topics/impala_perf_resources.xml
index 6ca1c08..3c1f8f3 100644
--- a/docs/topics/impala_perf_resources.xml
+++ b/docs/topics/impala_perf_resources.xml
@@ -51,8 +51,8 @@ under the License.
         limits on the number of concurrent queries or the amount of memory used. The queries are queued, and
         executed as other queries finish and resources become available. You can control the concurrency limits,
         and specify different limits for different groups of users to divide cluster resources according to the
-        priorities of different classes of users. This feature is new in Impala 1.3, and works with both CDH 4 and
-        CDH 5. See <xref href="impala_admission.xml#admission_control"/> for details.
+        priorities of different classes of users. This feature is new in Impala 1.3.
+        See <xref href="impala_admission.xml#admission_control"/> for details.
       </li>
 
       <li>

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_scalability.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_scalability.xml b/docs/topics/impala_scalability.xml
index 2362110..9bc8b7c 100644
--- a/docs/topics/impala_scalability.xml
+++ b/docs/topics/impala_scalability.xml
@@ -200,7 +200,7 @@ Memory Usage: Additional Notes
     <conbody>
 
       <p>
-        Before CDH 5.3, the statestore sent only one kind of message to its subscribers. This message contained all
+        Before <keyword keyref="impala21_full"/>, the statestore sent only one kind of message to its subscribers. This message contained all
         updates for any topics that a subscriber had subscribed to. It also served to let subscribers know that the
         statestore had not failed, and conversely the statestore used the success of sending a heartbeat to a
         subscriber to decide whether or not the subscriber had failed.
@@ -216,7 +216,7 @@ Memory Usage: Additional Notes
       </p>
 
       <p>
-        As of CDH 5.3, the statestore now sends topic updates and heartbeats in separate messages. This allows the
+        As of <keyword keyref="impala21_full"/>, the statestore now sends topic updates and heartbeats in separate messages. This allows the
         statestore to send and receive a steady stream of lightweight heartbeats, and removes the requirement to
         send topic updates according to a fixed schedule, reducing statestore network overhead.
       </p>
@@ -424,7 +424,7 @@ Memory Usage: Additional Notes
       </p>
 
       <p rev="2.2.0">
-        Prior to Impala 2.2 (CDH 5.4), the extra memory buffer for an operator that might spill to disk
+        Prior to Impala 2.2, the extra memory buffer for an operator that might spill to disk
         was allocated when the data structure used by the applicable SQL operator reaches 16 MB in size,
         and the memory buffer itself was 512 MB. In Impala 2.2, these values are halved: the threshold value
         is 8 MB and the memory buffer is 256 MB. <ph rev="2.3.0">In <keyword keyref="impala23_full"/> and higher, the memory for the buffer
@@ -442,10 +442,10 @@ Memory Usage: Additional Notes
       </p>
 
       <p>
-        <b>Added in:</b> This feature was added to the <codeph>ORDER BY</codeph> clause in Impala 1.4 for CDH 4,
-        and in CDH 5.1. This feature was extended to cover join queries, aggregation functions, and analytic
-        functions in Impala 2.0 for CDH 4, and in CDH 5.2. The size of the memory work area required by
-        each operator that spills was reduced from 512 megabytes to 256 megabytes in Impala 2.2 (CDH 5.4).
+        <b>Added in:</b> This feature was added to the <codeph>ORDER BY</codeph> clause in Impala 1.4.
+        This feature was extended to cover join queries, aggregation functions, and analytic
+        functions in Impala 2.0. The size of the memory work area required by
+        each operator that spills was reduced from 512 megabytes to 256 megabytes in Impala 2.2.
       </p>
 
       <p>

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_subqueries.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_subqueries.xml b/docs/topics/impala_subqueries.xml
index b8190bf..d3d509c 100644
--- a/docs/topics/impala_subqueries.xml
+++ b/docs/topics/impala_subqueries.xml
@@ -227,7 +227,7 @@ Therefore, this is not an efficient construct to use with Impala queries for HBa
     </p>
 
     <p>
-      <b>Added in:</b> Subqueries are substantially enhanced starting in Impala 2.0 for CDH 4, and CDH 5.2.0. Now,
+      <b>Added in:</b> Subqueries are substantially enhanced starting in Impala 2.0. Now,
       they can be used in the <codeph>WHERE</codeph> clause, in combination with clauses such as
       <codeph>EXISTS</codeph> and <codeph>IN</codeph>, rather than just in the <codeph>FROM</codeph> clause.
     </p>

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_txtfile.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_txtfile.xml b/docs/topics/impala_txtfile.xml
index 659d9f0..4b29bf0 100644
--- a/docs/topics/impala_txtfile.xml
+++ b/docs/topics/impala_txtfile.xml
@@ -537,8 +537,8 @@ INSERT INTO csv SELECT * FROM other_file_format_table;</codeblock>
 
             <note rev="1.2.0">
               <p rev="1.2.0">
-                <ph rev="upstream">The name of the Hadoop LZO package changed between CDH 4 and CDH 5. In CDH 4, the package name was
-                <codeph>hadoop-lzo-cdh4</codeph>. In CDH 5 and higher, the package name is <codeph>hadoop-lzo</codeph>.</ph>
+                The name of the Hadoop LZO package changed in the distant past.
+                Currently, the package name is <codeph>hadoop-lzo</codeph>.
               </p>
             </note>
 

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0ad55ba5/docs/topics/impala_udf.xml
----------------------------------------------------------------------
diff --git a/docs/topics/impala_udf.xml b/docs/topics/impala_udf.xml
index 7e529a7..1f63ec1 100644
--- a/docs/topics/impala_udf.xml
+++ b/docs/topics/impala_udf.xml
@@ -204,7 +204,7 @@ select real_words(letters) from word_games;</codeblock>
             Typically, a Java UDF will execute several times slower in Impala than the equivalent native UDF
             written in C++.
           </li>
-          <li rev="2.5.0 IMPALA-2843 CDH-39148">
+          <li rev="2.5.0 IMPALA-2843">
             In <keyword keyref="impala25_full"/> and higher, you can transparently call Hive Java UDFs through Impala,
             or call Impala Java UDFs through Hive. This feature does not apply to built-in Hive functions.
             Any Impala Java UDFs created with older versions must be re-created using new <codeph>CREATE FUNCTION</codeph>
@@ -282,7 +282,7 @@ select real_words(letters) from word_games;</codeblock>
             <codeph>WHERE</codeph> clause), directly on a column, and on the results of a string expression:
           </p>
 
-<!-- To do: adapt for signatureless syntax per CDH-39148 / IMPALA-2843. -->
+<!-- To do: adapt for signatureless syntax per IMPALA-2843. -->
 <codeblock>[localhost:21000] &gt; create database udfs;
 [localhost:21000] &gt; use udfs;
 localhost:21000] &gt; create function lower(string) returns string location '/user/hive/udfs/hive.jar' symbol='org.apache.hadoop.hive.ql.udf.UDFLower';
@@ -414,7 +414,7 @@ and other examples demonstrating this technique in
 
     <conbody>
 
-      <p rev="CDH-37080">
+      <p rev="">
         To develop UDFs for Impala, download and install the <codeph>impala-udf-devel</codeph> package (RHEL-based
         distributions) or <codeph>impala-udf-dev</codeph> (Ubuntu and Debian). This package contains
         header files, sample source, and build configuration files.
@@ -422,18 +422,16 @@ and other examples demonstrating this technique in
 
       <ol>
         <li>
-          Start at <xref href="https://archive.cloudera.com/cdh5/" scope="external" format="html"/> for the CDH 5
-          package, or <xref href="https://archive.cloudera.com/impala/" scope="external" format="html"/> for the CDH
-          4 package.
+          Start at <xref href="https://archive.cloudera.com/cdh5/" scope="external" format="html"/>.
         </li>
 
         <li>
           Locate the appropriate <codeph>.repo</codeph> or list file for your operating system version, such as
           <xref href="https://archive.cloudera.com/impala/redhat/6/x86_64/impala/cloudera-impala.repo" scope="external" format="html">the
-          <codeph>.repo</codeph> file for CDH 4 on RHEL 6</xref>.
+          <codeph>.repo</codeph> file for RHEL 6</xref>.
         </li>
 
-        <li rev="CDH-37080">
+        <li>
           Use the familiar <codeph>yum</codeph>, <codeph>zypper</codeph>, or <codeph>apt-get</codeph> commands
           depending on your operating system. For the package name, specify <codeph>impala-udf-devel</codeph>
           (RHEL-based distributions) or <codeph>impala-udf-dev</codeph> (Ubuntu and Debian).
@@ -1253,7 +1251,7 @@ StringVal StringConcatFinalize(FunctionContext* context, const StringVal&amp; va
       </conbody>
     </concept>
 
-    <concept rev="2.3.0 IMPALA-1829 CDH-30572" id="udf_intermediate">
+    <concept rev="2.3.0 IMPALA-1829" id="udf_intermediate">
 
       <title>Intermediate Results for UDAs</title>
 
@@ -1346,7 +1344,7 @@ StringVal StringConcatFinalize(FunctionContext* context, const StringVal&amp; va
         Prerequisites for the build environment are:
       </p>
 
-<codeblock rev="CDH-37080"># Use the appropriate package installation command for your Linux distribution.
+<codeblock rev=""># Use the appropriate package installation command for your Linux distribution.
 sudo yum install gcc-c++ cmake boost-devel
 sudo yum install impala-udf-devel
 # The package name on Ubuntu and Debian is impala-udf-dev.


[2/3] incubator-impala git commit: IMPALA-4813: Round on divide and multiply

Posted by jr...@apache.org.
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 <dh...@cloudera.com>
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 <za...@cloudera.com>
Authored: Fri Feb 24 00:55:38 2017 +0000
Committer: Impala Public Jenkins <im...@gerrit.cloudera.org>
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;