You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by ta...@apache.org on 2018/02/23 00:13:48 UTC

[1/3] impala git commit: IMPALA-4167: Support insert plan hints for CREATE TABLE AS SELECT

Repository: impala
Updated Branches:
  refs/heads/master 623ace0e4 -> 0c8eba076


IMPALA-4167: Support insert plan hints for CREATE TABLE AS SELECT

This change adds support for "clustered", "noclustered", "shuffle" and
"noshuffle" hints in CTAS statement.

Example:
create /*+ clustered,noshuffle */ table t partitioned by (year, month)
as select * from functional.alltypes

The effect of these hints are the same as in insert statements:

clustered:
Sort locally by partition expression before insert to ensure that only
one partition is written at a time. The goal is to reduce the number of
files kept open / buffers kept in memory simultaneously.

noclustered:
Do not sort by primary key before insert to Kudu table. No effect on HDFS
tables currently, as this is their default behavior.

shuffle:
Forces the planner to add an exchange node that repartitions by the
partition expression of the output table. This means that a partition
will be written only by a single node, which minimizes the global
number of simultaneous writes.
If only one partition is written (because all partitioning columns
are constant or the target table is not partitioned), then the shuffle
hint leads to a plan where all rows are merged at the coordinator where
the table sink is executed.

noshuffle:
Do not add exchange node before insert to partitioned tables.

The parser needed some modifications to be able to differentiate between
CREATE statements that allow hints (CTAS), and CREATE statements that
do not (every other type of CREATE statements). As a result, KW_CREATE
was moved from tbl_def_without_col_defs to statement rules.

Testing:

The parser tests mirror the tests of INSERT, while analysis and planner
tests are minimal, as the underlying logic is the same as for INSERT.

Query tests are not created, as the hints have no effect on
the DDL part of CTAS, and the actual query ran is the same as in
the insert case.

Change-Id: I8d74bca999da8ae1bb89427c70841f33e3c56ab0
Reviewed-on: http://gerrit.cloudera.org:8080/8400
Reviewed-by: Alex Behm <al...@cloudera.com>
Tested-by: Impala Public Jenkins


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

Branch: refs/heads/master
Commit: 5a1f432e8198e3eab7197a3b09455b57ab4b4412
Parents: 623ace0
Author: Csaba Ringhofer <cs...@cloudera.com>
Authored: Thu Oct 26 22:15:51 2017 +0200
Committer: Impala Public Jenkins <im...@gerrit.cloudera.org>
Committed: Thu Feb 22 20:43:44 2018 +0000

----------------------------------------------------------------------
 fe/src/main/cup/sql-parser.cup                  | 54 ++++++++----
 .../analysis/CreateTableAsSelectStmt.java       | 37 ++++++---
 .../apache/impala/analysis/AnalyzeDDLTest.java  | 28 +++++++
 .../impala/analysis/AnalyzeStmtsTest.java       |  7 +-
 .../org/apache/impala/analysis/ParserTest.java  | 86 +++++++++++++-------
 .../org/apache/impala/analysis/ToSqlTest.java   |  7 +-
 .../apache/impala/common/FrontendTestBase.java  |  5 ++
 .../queries/PlannerTest/ddl.test                | 31 +++++++
 .../queries/PlannerTest/kudu.test               | 21 +++++
 9 files changed, 211 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/fe/src/main/cup/sql-parser.cup
----------------------------------------------------------------------
diff --git a/fe/src/main/cup/sql-parser.cup b/fe/src/main/cup/sql-parser.cup
index 38183f8..9f55dda 100644
--- a/fe/src/main/cup/sql-parser.cup
+++ b/fe/src/main/cup/sql-parser.cup
@@ -383,7 +383,7 @@ nonterminal Subquery subquery;
 nonterminal JoinOperator join_operator;
 nonterminal opt_inner, opt_outer;
 nonterminal PlanHint plan_hint;
-nonterminal List<PlanHint> opt_plan_hints, plan_hint_list;
+nonterminal List<PlanHint> plan_hints, opt_plan_hints, plan_hint_list;
 nonterminal TypeDef type_def;
 nonterminal Type type;
 nonterminal Expr sign_chain_expr;
@@ -417,6 +417,7 @@ nonterminal DropStatsStmt drop_stats_stmt;
 nonterminal DropTableOrViewStmt drop_tbl_or_view_stmt;
 nonterminal CreateDbStmt create_db_stmt;
 nonterminal CreateTableAsSelectStmt create_tbl_as_select_stmt;
+nonterminal CreateTableAsSelectStmt.CtasParams create_tbl_as_select_params;
 nonterminal CreateTableLikeStmt create_tbl_like_stmt;
 nonterminal CreateTableStmt create_tbl_stmt;
 nonterminal TableDef tbl_def_without_col_defs, tbl_def_with_col_defs;
@@ -1103,13 +1104,30 @@ create_db_stmt ::=
   {: RESULT = new CreateDbStmt(db_name, comment, location, if_not_exists); :}
   ;
 
+
+// Merging the two cases using opt_plan_hints would lead to reduce-reduce conflict,
+// because if there are no hints, CTAS cannot be distinguished from normal CREATE
+// statements until the AS SELECT part, but the decision whether to reduce empty string
+// to opt_plan_hints must happen before reaching that part.
 create_tbl_as_select_stmt ::=
+  KW_CREATE create_tbl_as_select_params:ctas_params
+  {:
+    RESULT = new CreateTableAsSelectStmt(ctas_params, null);
+  :}
+  | KW_CREATE plan_hints:hints create_tbl_as_select_params:ctas_params
+  {:
+    RESULT = new CreateTableAsSelectStmt(ctas_params, hints);
+  :}
+  ;
+
+create_tbl_as_select_params ::=
   tbl_def_without_col_defs:tbl_def
   tbl_options:options
   KW_AS query_stmt:select_stmt
   {:
     tbl_def.setOptions(options);
-    RESULT = new CreateTableAsSelectStmt(new CreateTableStmt(tbl_def), select_stmt, null);
+    RESULT = new CreateTableAsSelectStmt.CtasParams(new CreateTableStmt(tbl_def),
+        select_stmt, null);
   :}
   | tbl_def_without_col_defs:tbl_def
     // An optional clause cannot be used directly below because it would conflict with
@@ -1122,7 +1140,8 @@ create_tbl_as_select_stmt ::=
     tbl_def.getPrimaryKeyColumnNames().addAll(primary_keys);
     tbl_def.getKuduPartitionParams().addAll(partition_params.getKuduPartitionParams());
     tbl_def.setOptions(options);
-    RESULT = new CreateTableAsSelectStmt(new CreateTableStmt(tbl_def), select_stmt, null);
+    RESULT = new CreateTableAsSelectStmt.CtasParams(new CreateTableStmt(tbl_def),
+        select_stmt, null);
   :}
   | tbl_def_without_col_defs:tbl_def
     KW_PARTITIONED KW_BY LPAREN ident_list:partition_cols RPAREN
@@ -1130,19 +1149,19 @@ create_tbl_as_select_stmt ::=
     KW_AS query_stmt:select_stmt
   {:
     tbl_def.setOptions(options);
-    RESULT = new CreateTableAsSelectStmt(new CreateTableStmt(tbl_def),
+    RESULT = new CreateTableAsSelectStmt.CtasParams(new CreateTableStmt(tbl_def),
         select_stmt, partition_cols);
   :}
   ;
 
 create_tbl_stmt ::=
-  tbl_def_without_col_defs:tbl_def
+  KW_CREATE tbl_def_without_col_defs:tbl_def
   tbl_options:options
   {:
     tbl_def.setOptions(options);
     RESULT = new CreateTableStmt(tbl_def);
   :}
-  | tbl_def_without_col_defs:tbl_def
+  | KW_CREATE tbl_def_without_col_defs:tbl_def
     // If "opt_tbl_data_layout" were used instead so that this rule could be combined with
     // the rule above, there would be a conflict with the first rule in
     // "create_tbl_as_select_stmt".
@@ -1154,7 +1173,7 @@ create_tbl_stmt ::=
     create_tbl_stmt.getPartitionColumnDefs().addAll(partition_column_defs);
     RESULT = create_tbl_stmt;
   :}
-  | tbl_def_with_col_defs:tbl_def
+  | KW_CREATE tbl_def_with_col_defs:tbl_def
     opt_tbl_data_layout:data_layout
     tbl_options:options
   {:
@@ -1163,7 +1182,7 @@ create_tbl_stmt ::=
     tbl_def.setOptions(options);
     RESULT = new CreateTableStmt(tbl_def);
   :}
-  | tbl_def_with_col_defs:tbl_def
+  | KW_CREATE tbl_def_with_col_defs:tbl_def
     KW_PRODUCED KW_BY KW_DATA source_ident:is_source_id ident_or_default:data_src_name
     opt_init_string_val:init_string
     opt_comment_val:comment
@@ -1177,7 +1196,7 @@ create_tbl_stmt ::=
     RESULT = new CreateTableDataSrcStmt(new CreateTableStmt(tbl_def),
         data_src_name, init_string);
   :}
-  | tbl_def_without_col_defs:tbl_def
+  | KW_CREATE tbl_def_without_col_defs:tbl_def
     KW_LIKE file_format_val:schema_file_format
     STRING_LITERAL:schema_location
     opt_tbl_data_layout:data_layout
@@ -1197,7 +1216,7 @@ create_tbl_stmt ::=
 // TODO: Refactor the CREATE TABLE statements to improve the grammar and the way we
 // handle table options.
 create_tbl_like_stmt ::=
-  tbl_def_without_col_defs:tbl_def
+  KW_CREATE tbl_def_without_col_defs:tbl_def
   KW_LIKE table_name:other_table
   opt_comment_val:comment
   file_format_create_table_val:file_format location_val:location
@@ -1207,7 +1226,7 @@ create_tbl_like_stmt ::=
   :}
   // This extra production is necessary since without it the parser will not be able to
   // parse "CREATE TABLE A LIKE B".
-  | tbl_def_without_col_defs:tbl_def
+  | KW_CREATE tbl_def_without_col_defs:tbl_def
     opt_sort_cols:sort_cols
     KW_LIKE table_name:other_table
     opt_comment_val:comment
@@ -1221,8 +1240,8 @@ create_tbl_like_stmt ::=
 // Used for creating tables where the schema is inferred externally, e.g., from an Avro
 // schema, Kudu table or query statement.
 tbl_def_without_col_defs ::=
-  KW_CREATE external_val:external KW_TABLE if_not_exists_val:if_not_exists
-  table_name:table
+  external_val:external KW_TABLE
+  if_not_exists_val:if_not_exists table_name:table
   {: RESULT = new TableDef(table, external, if_not_exists); :}
   ;
 
@@ -2529,6 +2548,13 @@ opt_outer ::=
   ;
 
 opt_plan_hints ::=
+  plan_hints:hints
+  {: RESULT = hints; :}
+  | /* empty */
+  {: RESULT = Lists.newArrayList(); :}
+  ;
+
+plan_hints ::=
   COMMENTED_PLAN_HINT_START plan_hint_list:hints COMMENTED_PLAN_HINT_END
   {: RESULT = hints; :}
   /* legacy straight_join hint style */
@@ -2537,8 +2563,6 @@ opt_plan_hints ::=
   /* legacy plan-hint style */
   | LBRACKET plan_hint_list:hints RBRACKET
   {: RESULT = hints; :}
-  | /* empty */
-  {: RESULT = Lists.newArrayList(); :}
   ;
 
 plan_hint ::=

http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java b/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java
index c5c092d..222b99a 100644
--- a/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java
@@ -66,23 +66,40 @@ public class CreateTableAsSelectStmt extends StatementBase {
       EnumSet.of(THdfsFileFormat.PARQUET, THdfsFileFormat.TEXT, THdfsFileFormat.KUDU);
 
   /**
+   * Helper class for parsing.
+   * Contains every parameter of the constructor with the exception of hints. This is
+   * needed to keep the production rules that check for optional hints separate from the
+   * rules that check for optional partition info. Merging these independent rules would
+   * make it necessary to create rules for every combination of them.
+   */
+  public static class CtasParams {
+    public CreateTableStmt createStmt;
+    public QueryStmt queryStmt;
+    public List<String> partitionKeys;
+
+    public CtasParams(CreateTableStmt createStmt, QueryStmt queryStmt,
+        List<String> partitionKeys) {
+      this.createStmt = Preconditions.checkNotNull(createStmt);
+      this.queryStmt = Preconditions.checkNotNull(queryStmt);
+      this.partitionKeys = partitionKeys;
+    }
+  }
+
+  /**
    * Builds a CREATE TABLE AS SELECT statement
    */
-  public CreateTableAsSelectStmt(CreateTableStmt createStmt, QueryStmt queryStmt,
-      List<String> partitionKeys) {
-    Preconditions.checkNotNull(queryStmt);
-    Preconditions.checkNotNull(createStmt);
-    createStmt_ = createStmt;
-    partitionKeys_ = partitionKeys;
+  public CreateTableAsSelectStmt(CtasParams params, List<PlanHint> planHints) {
+    createStmt_ = params.createStmt;
+    partitionKeys_ = params.partitionKeys;
     List<PartitionKeyValue> pkvs = null;
-    if (partitionKeys != null) {
+    if (partitionKeys_ != null) {
       pkvs = Lists.newArrayList();
-      for (String key: partitionKeys) {
+      for (String key: partitionKeys_) {
         pkvs.add(new PartitionKeyValue(key, null));
       }
     }
-    insertStmt_ = InsertStmt.createInsert(
-        null, createStmt.getTblName(), false, pkvs, null, null, queryStmt, null);
+    insertStmt_ = InsertStmt.createInsert(null, createStmt_.getTblName(), false, pkvs,
+        planHints, null, params.queryStmt, null);
   }
 
   public QueryStmt getQueryStmt() { return insertStmt_.getQueryStmt(); }

http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
index ee4ed0e..56f81e3 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
@@ -1830,6 +1830,34 @@ public class AnalyzeDDLTest extends FrontendTestBase {
   }
 
   @Test
+  public void TestCreateTableAsSelectWithHints() throws AnalysisException {
+    // Test if CTAS hints are analyzed correctly and that conflicting hints
+    // result in error.
+    // The tests here are minimal, because other tests already cover this logic:
+    // - ParserTests#TestPlanHints tests if hints are set correctly during parsing.
+    // - AnalyzeStmtsTest#TestInsertHints tests the analyzes of insert hints, which
+    //   is the same as the analyzes of CTAS hints.
+    for (String[] hintStyle: hintStyles_) {
+      String prefix = hintStyle[0];
+      String suffix = hintStyle[1];
+      // Test plan hints for partitioned Hdfs tables.
+      AnalyzesOk(String.format("create %sshuffle%s table t " +
+          "partitioned by (year, month) as select * from functional.alltypes",
+          prefix, suffix));
+      // Warn on unrecognized hints.
+      AnalyzesOk(String.format("create %sbadhint%s table t " +
+          "partitioned by (year, month) as select * from functional.alltypes",
+          prefix, suffix),
+          "INSERT hint not recognized: badhint");
+      // Conflicting plan hints.
+      AnalysisError(String.format("create %sshuffle,noshuffle%s table t " +
+          "partitioned by (year, month) as " +
+          "select * from functional.alltypes", prefix, suffix),
+          "Conflicting INSERT hints: shuffle and noshuffle");
+    }
+  }
+
+  @Test
   public void TestCreateTableLike() throws AnalysisException {
     AnalyzesOk("create table if not exists functional.new_tbl like functional.alltypes");
     AnalyzesOk("create table functional.like_view like functional.view_view");

http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java
index 36d6970..deeb0a8 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeStmtsTest.java
@@ -1820,12 +1820,7 @@ public class AnalyzeStmtsTest extends AnalyzerTest {
 
   @Test
   public void TestSelectListHints() throws AnalysisException {
-    String[][] hintStyles = new String[][] {
-        new String[] { "/* +", "*/" }, // traditional commented hint
-        new String[] { "\n-- +", "\n" }, // eol commented hint
-        new String[] { "", "" } // without surrounding characters
-    };
-    for (String[] hintStyle: hintStyles) {
+    for (String[] hintStyle: hintStyles_) {
       String prefix = hintStyle[0];
       String suffix = hintStyle[1];
       AnalyzesOk(String.format(

http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/analysis/ParserTest.java b/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
index 8dd4898..178539f 100644
--- a/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
@@ -300,11 +300,19 @@ public class ParserTest extends FrontendTestBase {
     assertEquals(Lists.newArrayList(expectedHints), actualHints);
   }
 
-  private void VerifyHints(List<PlanHint> actualHints, String... expectedHints) {
-    List<String> stringHints = Lists.newArrayList();
-    for (PlanHint hint: actualHints) stringHints.add(hint.toString());
-    if (stringHints.isEmpty()) stringHints = Lists.newArrayList((String) null);
-    assertEquals(Lists.newArrayList(expectedHints), stringHints);
+  /**
+   * Creates an insert into, an insert overwrite, and a CTAS statement with
+   * the given hints and checks that the parsed hints are the same as the expected hints.
+   */
+  private void TestInsertAndCtasHints(String insertPart, String ctasPart,
+        String[] hintStyle, String hints, String... expectedHints) {
+    String hintsPart = hintStyle[0] + hints + hintStyle[1];
+    TestInsertStmtHints(String.format("insert %%s into %s %%s select * from t",
+        insertPart), hintsPart, expectedHints);
+    TestInsertStmtHints(String.format("insert %%s overwrite %s %%s select * from t",
+        insertPart), hintsPart, expectedHints);
+    TestCtasHints(String.format("create %s table %s as select * from t",
+        hintsPart, ctasPart), expectedHints);
   }
 
   /**
@@ -313,8 +321,8 @@ public class ParserTest extends FrontendTestBase {
    */
   private void TestInsertStmtHints(String pattern, String hint, String... expectedHints) {
     for (InsertStmt.HintLocation loc: InsertStmt.HintLocation.values()) {
-      VerifyHints(((InsertStmt) ParsesOk(InjectInsertHint(pattern, hint, loc)))
-          .getPlanHints(), expectedHints);
+      InsertStmt insertStmt = (InsertStmt) ParsesOk(InjectInsertHint(pattern, hint, loc));
+      assertEquals(expectedHints, HintsToStrings(insertStmt.getPlanHints()));
     }
   }
 
@@ -328,20 +336,28 @@ public class ParserTest extends FrontendTestBase {
     }
   }
 
+  /**
+   * Parses stmt and checks that the CTAS hints stmt are the expected hints.
+   */
+  private void TestCtasHints(String stmt, String... expectedHints) {
+    CreateTableAsSelectStmt ctasStmt = (CreateTableAsSelectStmt) ParsesOk(stmt);
+    assertEquals(expectedHints, HintsToStrings(ctasStmt.getInsertStmt().getPlanHints()));
+  }
+
+  static private String[] HintsToStrings(List<PlanHint> hints) {
+    if (hints.isEmpty()) return new String[] { null };
+    String[] hintAsStrings = new String[hints.size()];
+    for (int i = 0; i < hints.size(); ++i) hintAsStrings[i] = hints.get(i).toString();
+    return hintAsStrings;
+  }
+
   @Test
   public void TestPlanHints() {
-    // All plan-hint styles embed a comma-separated list of hints.
-    String[][] hintStyles = new String[][] {
-        new String[] { "/* +", "*/" }, // traditional commented hint
-        new String[] { "-- +", "\n" }, // eol commented hint
-        new String[] { "\n-- +", "\n" }, // eol commented hint
-        new String[] { "[", "]" } // legacy style
-    };
     String[][] commentStyles = new String[][] {
         new String[] { "/*", "*/" }, // traditional comment
         new String[] { "--", "\n" } // eol comment
     };
-    for (String[] hintStyle: hintStyles) {
+    for (String[] hintStyle: hintStyles_) {
       String prefix = hintStyle[0];
       String suffix = hintStyle[1];
       // Test join hints.
@@ -389,17 +405,14 @@ public class ParserTest extends FrontendTestBase {
               "join %sshuffle%s functional.alltypes e using(string_col)",
               suffix, suffix, suffix, suffix, prefix, "", "", ""));
 
-      // Test insert hints.
-      TestInsertStmtHints("insert %s into t %s select * from t",
-           String.format("%snoshuffle%s", prefix, suffix), "noshuffle");
-      TestInsertStmtHints("insert %s overwrite t %s select * from t",
-           String.format("%snoshuffle%s", prefix, suffix), "noshuffle");
-      TestInsertStmtHints("insert %s into t partition(x, y) %s select * from t",
-           String.format("%snoshuffle%s", prefix, suffix), "noshuffle");
-      TestInsertStmtHints("insert %s into t(a, b) partition(x, y) %s select * from t",
-           String.format("%sshuffle%s", prefix, suffix), "shuffle");
-      TestInsertStmtHints("insert %s overwrite t(a, b) partition(x, y) %s select * from t",
-           String.format("%sfoo,bar,baz%s", prefix, suffix), "foo", "bar", "baz");
+      // Test insert/CTAS hints.
+      TestInsertAndCtasHints("t", "t", hintStyle, "noshuffle", "noshuffle");
+      TestInsertAndCtasHints("t partition(x, y)", "t partitioned by(x, y)",
+          hintStyle, "noshuffle", "noshuffle");
+      TestInsertAndCtasHints("t(a, b) partition(x, y)", "t partitioned by(x, y)",
+          hintStyle, "shuffle", "shuffle");
+      TestInsertAndCtasHints("t(a, b) partition(x, y)", "t partitioned by(x, y)",
+          hintStyle, "foo,bar,baz", "foo", "bar", "baz");
 
       // Test upsert hints.
       TestInsertStmtHints("upsert %s into t %s select * from t",
@@ -488,14 +501,29 @@ public class ParserTest extends FrontendTestBase {
       ParserErrorOnInsertStmtHints("insert %s into t %s select * from t",
            String.format("%shint_with_args(  a  ,  , ,,, b  )%s", prefix, suffix));
 
-      // Negative tests for hints cannot be specified at the both avilable locations.
+      TestInsertAndCtasHints("t", "t",
+          hintStyle, "hint_with_args(a)", "hint_with_args(a)");
+      TestInsertAndCtasHints("t", "t",
+          hintStyle, "clustered,shuffle,hint_with_args(a)",
+          "clustered", "shuffle", "hint_with_args(a)");
+      TestInsertAndCtasHints("t", "t",
+          hintStyle, "hint_with_args(a,b)", "hint_with_args(a,b)");
+      TestInsertAndCtasHints("t", "t",
+          hintStyle, "hint_with_args(a  , b)", "hint_with_args(a,b)");
+
+      ParserErrorOnInsertStmtHints("insert %s into t %s select * from t",
+          String.format("%shint_with_args(  a  ,  , ,,, b  )%s", prefix, suffix));
+      ParserError(String.format(
+         "create table t %shint_with_args(  a  ,  , ,,, b  )%s as select * from t",
+         prefix, suffix));
+
+      // Negative tests for hints cannot be specified at the both available locations.
       ParserError(String.format("insert %s into t %s select * from t",
            String.format("%sshuffle%s", prefix, suffix),
            String.format("%sclustered%s", prefix, suffix)));
       ParserError(String.format("upsert %s into t %s select * from t",
            String.format("%sshuffle%s", prefix, suffix),
            String.format("%sclustered%s", prefix, suffix)));
-
     }
     // No "+" at the beginning so the comment is not recognized as a hint.
     TestJoinHints("select * from functional.alltypes a join /* comment */" +
@@ -504,6 +532,8 @@ public class ParserTest extends FrontendTestBase {
         (String) null);
     TestInsertStmtHints("insert %s into t(a, b) partition(x, y) %s select 1",
         "/* comment */", (String) null);
+    TestCtasHints("create /* comment */ table t partitioned by (x, y) as select 1",
+        (String) null);
     TestSelectListHints("select /* -- +straight_join */ * from functional.alltypes",
         (String) null);
     TestSelectListHints("select /* abcdef +straight_join */ * from functional.alltypes",

http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/fe/src/test/java/org/apache/impala/analysis/ToSqlTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/analysis/ToSqlTest.java b/fe/src/test/java/org/apache/impala/analysis/ToSqlTest.java
index a813cce..760ea59 100644
--- a/fe/src/test/java/org/apache/impala/analysis/ToSqlTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/ToSqlTest.java
@@ -546,12 +546,7 @@ public class ToSqlTest extends FrontendTestBase {
    */
   @Test
   public void planHintsTest() {
-    String[][] hintStyles = new String[][] {
-        new String[] { "/* +", "*/" }, // traditional commented hint
-        new String[] { "\n-- +", "\n" }, // eol commented hint
-        new String[] { "[", "]" } // legacy style
-    };
-    for (String[] hintStyle: hintStyles) {
+    for (String[] hintStyle: hintStyles_) {
       String prefix = hintStyle[0];
       String suffix = hintStyle[1];
 

http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java b/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
index 9be3343..28dc710 100644
--- a/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
+++ b/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
@@ -84,6 +84,11 @@ public class FrontendTestBase {
   // Test-local list of test databases and tables. These are cleaned up in @After.
   protected final List<Db> testDbs_ = Lists.newArrayList();
   protected final List<Table> testTables_ = Lists.newArrayList();
+  protected final String[][] hintStyles_ = new String[][] {
+      new String[] { "/* +", "*/" }, // traditional commented hint
+      new String[] { "\n-- +", "\n" }, // eol commented hint
+      new String[] { "[", "]" } // legacy style
+  };
 
   @BeforeClass
   public static void setUp() throws Exception {

http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/testdata/workloads/functional-planner/queries/PlannerTest/ddl.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/ddl.test b/testdata/workloads/functional-planner/queries/PlannerTest/ddl.test
index 0129ad1..74c7e5f 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/ddl.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/ddl.test
@@ -204,6 +204,37 @@ WRITE TO HDFS [default.t, OVERWRITE=false, PARTITION-KEYS=(year,month)]
 00:SCAN HDFS [functional.alltypes]
    partitions=24/24 files=24 size=478.45KB
 ====
+# IMPALA-4167: if no (no)shuffle hint is given for CTAS into partitioned HDFS table, then
+# Impala is free to decide whether to add an exchange node or not. In this example, the
+# planner decides to shuffle. The aim of this test is to have a reference query where
+# noshuffle hint would lead to a different plan.
+# Note that noclustered hint is added to ensure consistent plans on Impala 2.x and 3.x,
+# because IMPALA-5293 changed clustered to be the default on 3.x.
+create /*+ noclustered */table t partitioned by (year, month) as
+select * from functional.alltypes
+---- DISTRIBUTEDPLAN
+WRITE TO HDFS [default.t, OVERWRITE=false, PARTITION-KEYS=(functional.alltypes.year,functional.alltypes.month)]
+|  partitions=24
+|
+01:EXCHANGE [HASH(functional.alltypes.year,functional.alltypes.month)]
+|
+00:SCAN HDFS [functional.alltypes]
+   partitions=24/24 files=24 size=478.45KB
+====
+# IMPALA-4167: non-shuffled CTAS into partitioned table has no exchange node before write.
+# Note that plan hint tests for CTAS are minimal by design, as this logic is covered well
+# in insert.test.
+# Note that noclustered hint is added to ensure consistent plans on Impala 2.x and 3.x,
+# because IMPALA-5293 changed clustered to be the default on 3.x.
+create /*+ noshuffle, noclustered */ table t partitioned by (year, month) as
+select * from functional.alltypes
+---- DISTRIBUTEDPLAN
+WRITE TO HDFS [default.t, OVERWRITE=false, PARTITION-KEYS=(functional.alltypes.year,functional.alltypes.month)]
+|  partitions=24
+|
+00:SCAN HDFS [functional.alltypes]
+   partitions=24/24 files=24 size=478.45KB
+====
 # CTAS with more complex select query
 create table t partitioned by (c_nationkey) sort by (c_custkey) as
 select c_custkey, max(o_totalprice) as maxprice, c_nationkey

http://git-wip-us.apache.org/repos/asf/impala/blob/5a1f432e/testdata/workloads/functional-planner/queries/PlannerTest/kudu.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/kudu.test b/testdata/workloads/functional-planner/queries/PlannerTest/kudu.test
index 0e1b2c6..354a6fa 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/kudu.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/kudu.test
@@ -426,6 +426,27 @@ INSERT INTO KUDU [functional_kudu.alltypes]
 00:SCAN HDFS [functional.alltypes]
    partitions=24/24 files=24 size=478.45KB
 ====
+# Hint - noclustered should remove the sort node from CTAS.
+create /* +noclustered */ table t
+primary key(id) partition by hash(id) partitions 3 stored as kudu as
+select * from functional.alltypes;
+---- DISTRIBUTEDPLAN
+INSERT INTO KUDU [default.t]
+|
+01:EXCHANGE [KUDU(KuduPartition(functional.alltypes.id))]
+|
+00:SCAN HDFS [functional.alltypes]
+   partitions=24/24 files=24 size=478.45KB
+====
+create /* +noclustered,noshuffle */ table t
+primary key(id) partition by hash(id) partitions 3 stored as kudu as
+select * from functional.alltypes;
+---- DISTRIBUTEDPLAN
+INSERT INTO KUDU [default.t]
+|
+00:SCAN HDFS [functional.alltypes]
+   partitions=24/24 files=24 size=478.45KB
+====
 # IMPALA-5602: If a query contains predicates that are all pushed to kudu and there is a
 # limit, then the query should not incorrectly run with 'small query' optimization.
 select * from functional_kudu.alltypesagg where tinyint_col = 9 limit 10;


[3/3] impala git commit: IMPALA-5752: Add support for DECIMAL on Kudu tables

Posted by ta...@apache.org.
IMPALA-5752: Add support for DECIMAL on Kudu tables

Adds support for the Kudu DECIMAL type introduced in Kudu 1.7.0.

Note: Adding support for Kudu decimal min/max filters is
tracked in IMPALA-6533.

Tests:
* Added Kudu create with decimal test to AnalyzeDDLTest.java
* Added Kudu table_format to test_decimal_queries.py
** Both decimal.test and decimal-exprs.test workloads
* Added decimal queries to the following Kudu workloads:
** kudu_create.test
** kudu_delete.test
** kudu_insert.test
** kudu_update.test
** kudu_upsert.test

Change-Id: I3a9fe5acadc53ec198585d765a8cfb0abe56e199
Reviewed-on: http://gerrit.cloudera.org:8080/9368
Reviewed-by: Dimitris Tsirogiannis <dt...@cloudera.com>
Tested-by: Impala Public Jenkins


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

Branch: refs/heads/master
Commit: 0c8eba076c10eecde578917e7f8ef78bba983fc4
Parents: 5a1f432
Author: Grant Henke <gh...@cloudera.com>
Authored: Tue Feb 20 16:17:40 2018 -0600
Committer: Impala Public Jenkins <im...@gerrit.cloudera.org>
Committed: Fri Feb 23 00:03:54 2018 +0000

----------------------------------------------------------------------
 be/src/exec/kudu-scanner.cc                     |   6 +-
 be/src/exec/kudu-table-sink.cc                  |  10 +-
 be/src/exec/kudu-util.cc                        |  71 +++-
 be/src/exec/kudu-util.h                         |  27 +-
 be/src/exprs/kudu-partition-expr.cc             |   4 +-
 .../org/apache/impala/catalog/KuduColumn.java   |   2 +-
 .../org/apache/impala/planner/KuduScanNode.java |   3 +-
 .../impala/planner/RuntimeFilterGenerator.java  |   2 +
 .../impala/service/KuduCatalogOpExecutor.java   |  17 +-
 .../java/org/apache/impala/util/KuduUtil.java   |  43 +-
 .../apache/impala/analysis/AnalyzeDDLTest.java  |  19 +-
 .../functional/functional_schema_template.sql   |  31 ++
 .../datasets/functional/schema_constraints.csv  |   4 +
 .../queries/QueryTest/kudu_create.test          |  36 +-
 .../queries/QueryTest/kudu_delete.test          | 300 ++++++++------
 .../queries/QueryTest/kudu_describe.test        |  20 +
 .../queries/QueryTest/kudu_insert.test          | 255 ++++++------
 .../queries/QueryTest/kudu_update.test          | 270 +++++++------
 .../queries/QueryTest/kudu_upsert.test          | 392 ++++++++++---------
 tests/query_test/test_decimal_queries.py        |   4 +-
 tests/query_test/test_kudu.py                   |   3 +-
 21 files changed, 882 insertions(+), 637 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/be/src/exec/kudu-scanner.cc
----------------------------------------------------------------------
diff --git a/be/src/exec/kudu-scanner.cc b/be/src/exec/kudu-scanner.cc
index 909567c..3bc4441 100644
--- a/be/src/exec/kudu-scanner.cc
+++ b/be/src/exec/kudu-scanner.cc
@@ -185,7 +185,7 @@ Status KuduScanner::OpenNextScanToken(const string& scan_token, bool* eos) {
               ctx.filter->filter_desc().targets[it->second];
           const string& col_name = target_desc.kudu_col_name;
           DCHECK(col_name != "");
-          ColumnType col_type = ColumnType::FromThrift(target_desc.kudu_col_type);
+          const ColumnType& col_type = ColumnType::FromThrift(target_desc.kudu_col_type);
 
           void* min = filter->GetMin();
           void* max = filter->GetMax();
@@ -209,14 +209,14 @@ Status KuduScanner::OpenNextScanToken(const string& scan_token, bool* eos) {
           }
 
           KuduValue* min_value;
-          RETURN_IF_ERROR(CreateKuduValue(filter->type(), min, &min_value));
+          RETURN_IF_ERROR(CreateKuduValue(col_type, min, &min_value));
           KUDU_RETURN_IF_ERROR(
               scanner_->AddConjunctPredicate(scan_node_->table_->NewComparisonPredicate(
                   col_name, KuduPredicate::ComparisonOp::GREATER_EQUAL, min_value)),
               "Failed to add min predicate");
 
           KuduValue* max_value;
-          RETURN_IF_ERROR(CreateKuduValue(filter->type(), max, &max_value));
+          RETURN_IF_ERROR(CreateKuduValue(col_type, max, &max_value));
           KUDU_RETURN_IF_ERROR(
               scanner_->AddConjunctPredicate(scan_node_->table_->NewComparisonPredicate(
                   col_name, KuduPredicate::ComparisonOp::LESS_EQUAL, max_value)),

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/be/src/exec/kudu-table-sink.cc
----------------------------------------------------------------------
diff --git a/be/src/exec/kudu-table-sink.cc b/be/src/exec/kudu-table-sink.cc
index deb3b66..05f1d06 100644
--- a/be/src/exec/kudu-table-sink.cc
+++ b/be/src/exec/kudu-table-sink.cc
@@ -145,7 +145,9 @@ Status KuduTableSink::Open(RuntimeState* state) {
       return Status(strings::Substitute(
           "Table $0 has fewer columns than expected.", table_desc_->name()));
     }
-    ColumnType type = KuduDataTypeToColumnType(table_->schema().Column(col_idx).type());
+    const KuduColumnSchema& kudu_col = table_->schema().Column(col_idx);
+    const ColumnType& type =
+        KuduDataTypeToColumnType(kudu_col.type(), kudu_col.type_attributes());
     if (type != output_expr_evals_[i]->root().type()) {
       return Status(strings::Substitute("Column $0 has unexpected type. ($1 vs. $2)",
           table_->schema().Column(col_idx).name(), type.DebugString(),
@@ -256,13 +258,13 @@ Status KuduTableSink::Send(RuntimeState* state, RowBatch* batch) {
         }
       }
 
-      PrimitiveType type = output_expr_evals_[j]->root().type().type;
+      const ColumnType& type = output_expr_evals_[j]->root().type();
       Status s = WriteKuduValue(col, type, value, true, write->mutable_row());
       // This can only fail if we set a col to an incorrect type, which would be a bug in
       // planning, so we can DCHECK.
       DCHECK(s.ok()) << "WriteKuduValue failed for col = "
-                     << table_schema.Column(col).name() << " and type = "
-                     << output_expr_evals_[j]->root().type() << ": " << s.GetDetail();
+                     << table_schema.Column(col).name() << " and type = " << type << ": "
+                     << s.GetDetail();
       RETURN_IF_ERROR(s);
     }
     if (add_row) write_ops.push_back(move(write));

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/be/src/exec/kudu-util.cc
----------------------------------------------------------------------
diff --git a/be/src/exec/kudu-util.cc b/be/src/exec/kudu-util.cc
index d32df25..0538a61 100644
--- a/be/src/exec/kudu-util.cc
+++ b/be/src/exec/kudu-util.cc
@@ -28,6 +28,7 @@
 #include "common/logging.h"
 #include "common/names.h"
 #include "common/status.h"
+#include "runtime/decimal-value.h"
 #include "runtime/timestamp-value.h"
 #include "runtime/timestamp-value.inline.h"
 
@@ -35,6 +36,7 @@ using kudu::client::KuduSchema;
 using kudu::client::KuduClient;
 using kudu::client::KuduClientBuilder;
 using kudu::client::KuduColumnSchema;
+using kudu::client::KuduColumnTypeAttributes;
 using kudu::client::KuduValue;
 using DataType = kudu::client::KuduColumnSchema::DataType;
 
@@ -71,15 +73,6 @@ Status CreateKuduClient(const vector<string>& master_addrs,
   return Status::OK();
 }
 
-string KuduSchemaDebugString(const KuduSchema& schema) {
-  stringstream ss;
-  for (int i = 0; i < schema.num_columns(); ++i) {
-    const KuduColumnSchema& col = schema.Column(i);
-    ss << col.name() << " " << KuduColumnSchema::DataTypeToString(col.type()) << "\n";
-  }
-  return ss.str();
-}
-
 void LogKuduMessage(void* unused, kudu::client::KuduLogSeverity severity,
     const char* filename, int line_number, const struct ::tm* time, const char* message,
     size_t message_len) {
@@ -123,9 +116,10 @@ static Status ConvertTimestampValue(const TimestampValue* tv, int64_t* ts_micros
   return Status::OK();
 }
 
-Status WriteKuduValue(int col, PrimitiveType type, const void* value,
+Status WriteKuduValue(int col, const ColumnType& col_type, const void* value,
     bool copy_strings, kudu::KuduPartialRow* row) {
-  // TODO: codegen this to eliminate braching on type.
+  // TODO: codegen this to eliminate branching on type.
+  PrimitiveType type = col_type.type;
   switch (type) {
     case TYPE_VARCHAR:
     case TYPE_STRING: {
@@ -172,7 +166,31 @@ Status WriteKuduValue(int col, PrimitiveType type, const void* value,
       RETURN_IF_ERROR(ConvertTimestampValue(
           reinterpret_cast<const TimestampValue*>(value), &ts_micros));
       KUDU_RETURN_IF_ERROR(
-          row->SetUnixTimeMicros(col, ts_micros), "Could not add Kudu WriteOp.");
+          row->SetUnixTimeMicros(col, ts_micros), "Could not set Kudu row value.");
+      break;
+    case TYPE_DECIMAL:
+      switch (col_type.GetByteSize()) {
+        case 4:
+          KUDU_RETURN_IF_ERROR(
+              row->SetUnscaledDecimal(
+                  col, reinterpret_cast<const Decimal4Value*>(value)->value()),
+              "Could not set Kudu row value.");
+          break;
+        case 8:
+          KUDU_RETURN_IF_ERROR(
+              row->SetUnscaledDecimal(
+                  col, reinterpret_cast<const Decimal8Value*>(value)->value()),
+              "Could not set Kudu row value.");
+          break;
+        case 16:
+          KUDU_RETURN_IF_ERROR(
+              row->SetUnscaledDecimal(
+                  col, reinterpret_cast<const Decimal16Value*>(value)->value()),
+              "Could not set Kudu row value.");
+          break;
+        default:
+          DCHECK(false) << "Unknown decimal byte size: " << col_type.GetByteSize();
+      }
       break;
     default:
       return Status(TErrorCode::IMPALA_KUDU_TYPE_MISSING, TypeToString(type));
@@ -181,7 +199,8 @@ Status WriteKuduValue(int col, PrimitiveType type, const void* value,
   return Status::OK();
 }
 
-ColumnType KuduDataTypeToColumnType(DataType type) {
+ColumnType KuduDataTypeToColumnType(
+    DataType type, const KuduColumnTypeAttributes& type_attributes) {
   switch (type) {
     case DataType::INT8: return ColumnType(PrimitiveType::TYPE_TINYINT);
     case DataType::INT16: return ColumnType(PrimitiveType::TYPE_SMALLINT);
@@ -194,13 +213,14 @@ ColumnType KuduDataTypeToColumnType(DataType type) {
     case DataType::BINARY: return ColumnType(PrimitiveType::TYPE_BINARY);
     case DataType::UNIXTIME_MICROS: return ColumnType(PrimitiveType::TYPE_TIMESTAMP);
     case DataType::DECIMAL:
-      DCHECK(false) << "DECIMAL is not supported on Kudu.";
-      return ColumnType(PrimitiveType::INVALID_TYPE);
+      return ColumnType::CreateDecimalType(
+          type_attributes.precision(), type_attributes.scale());
   }
   return ColumnType(PrimitiveType::INVALID_TYPE);
 }
 
-Status CreateKuduValue(PrimitiveType type, void* value, KuduValue** out) {
+Status CreateKuduValue(const ColumnType& col_type, void* value, KuduValue** out) {
+  PrimitiveType type = col_type.type;
   switch (type) {
     case TYPE_VARCHAR:
     case TYPE_STRING: {
@@ -237,6 +257,25 @@ Status CreateKuduValue(PrimitiveType type, void* value, KuduValue** out) {
       *out = KuduValue::FromInt(ts_micros);
       break;
     }
+    case TYPE_DECIMAL: {
+      switch (col_type.GetByteSize()) {
+        case 4:
+          *out = KuduValue::FromDecimal(
+              reinterpret_cast<const Decimal4Value*>(value)->value(), col_type.scale);
+          break;
+        case 8:
+          *out = KuduValue::FromDecimal(
+              reinterpret_cast<const Decimal8Value*>(value)->value(), col_type.scale);
+          break;
+        case 16:
+          *out = KuduValue::FromDecimal(
+              reinterpret_cast<const Decimal16Value*>(value)->value(), col_type.scale);
+          break;
+        default:
+          DCHECK(false) << "Unknown decimal byte size: " << col_type.GetByteSize();
+      }
+      break;
+    }
     default:
       return Status(TErrorCode::IMPALA_KUDU_TYPE_MISSING, TypeToString(type));
   }

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/be/src/exec/kudu-util.h
----------------------------------------------------------------------
diff --git a/be/src/exec/kudu-util.h b/be/src/exec/kudu-util.h
index 5fd1140..36764d4 100644
--- a/be/src/exec/kudu-util.h
+++ b/be/src/exec/kudu-util.h
@@ -65,9 +65,6 @@ bool KuduIsAvailable();
 Status CreateKuduClient(const std::vector<std::string>& master_addrs,
     kudu::client::sp::shared_ptr<kudu::client::KuduClient>* client) WARN_UNUSED_RESULT;
 
-/// Returns a debug string for the KuduSchema.
-std::string KuduSchemaDebugString(const kudu::client::KuduSchema& schema);
-
 /// Initializes Kudu's logging by binding a callback that logs back to Impala's glog. This
 /// also sets Kudu's verbose logging to whatever level is set in Impala.
 void InitKuduLogging();
@@ -78,20 +75,22 @@ void InitKuduLogging();
 void LogKuduMessage(kudu::client::KuduLogSeverity severity, const char* filename,
     int line_number, const struct ::tm* time, const char* message, size_t message_len);
 
-/// Casts 'value' according to 'type' and writes it into 'row' at position 'col'.
-/// If 'type' is STRING or VARCHAR, 'copy_strings' determines if 'value' will be copied
-/// into memory owned by the row. If false, string data must remain valid while the row
-/// is being used.
-Status WriteKuduValue(int col, PrimitiveType type, const void* value,
+/// Casts 'value' according to the column type in 'col_type' and writes it into 'row'
+/// at position 'col'. If the column type's primitive type is STRING or VARCHAR,
+/// 'copy_strings' determines if 'value' will be copied into memory owned by the row.
+/// If false, string data must remain valid while the row is being used.
+Status WriteKuduValue(int col, const ColumnType& col_type, const void* value,
     bool copy_strings, kudu::KuduPartialRow* row) WARN_UNUSED_RESULT;
 
-/// Casts 'value' according to 'type' and create a new KuduValue containing 'value' which
-/// is returned in 'out'.
-Status CreateKuduValue(
-    PrimitiveType type, void* value, kudu::client::KuduValue** out) WARN_UNUSED_RESULT;
+/// Casts 'value' according to the column type in 'col_type' and create a
+/// new KuduValue containing 'value' which is returned in 'out'.
+Status CreateKuduValue(const ColumnType& col_type, void* value,
+    kudu::client::KuduValue** out) WARN_UNUSED_RESULT;
 
-/// Takes a Kudu client DataType and returns the corresponding Impala ColumnType.
-ColumnType KuduDataTypeToColumnType(kudu::client::KuduColumnSchema::DataType type);
+/// Takes a Kudu client DataType and KuduColumnTypeAttributes and
+/// returns the corresponding Impala ColumnType.
+ColumnType KuduDataTypeToColumnType(kudu::client::KuduColumnSchema::DataType type,
+    const kudu::client::KuduColumnTypeAttributes& type_attributes);
 
 /// Utility function for creating an Impala Status object based on a kudu::Status object.
 /// 'k_status' is the kudu::Status object.

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/be/src/exprs/kudu-partition-expr.cc
----------------------------------------------------------------------
diff --git a/be/src/exprs/kudu-partition-expr.cc b/be/src/exprs/kudu-partition-expr.cc
index 2cc96f0..ce38e24 100644
--- a/be/src/exprs/kudu-partition-expr.cc
+++ b/be/src/exprs/kudu-partition-expr.cc
@@ -70,8 +70,8 @@ IntVal KuduPartitionExpr::GetIntVal(ScalarExprEvaluator* eval,
     }
     int col = tkudu_partition_expr_.referenced_columns[i];
     const ColumnDescriptor& col_desc = table_desc_->col_descs()[col];
-    PrimitiveType type = col_desc.type().type;
-    DCHECK_EQ(GetChild(i)->type().type, type);
+    const ColumnType& type = col_desc.type();
+    DCHECK_EQ(GetChild(i)->type().type, type.type);
     Status s = WriteKuduValue(col, type, val, false, row_.get());
     // This can only fail if we set a col to an incorect type, which would be a bug in
     // planning, so we can DCHECK.

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/fe/src/main/java/org/apache/impala/catalog/KuduColumn.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/catalog/KuduColumn.java b/fe/src/main/java/org/apache/impala/catalog/KuduColumn.java
index 2dd3e85..a4b8e5f 100644
--- a/fe/src/main/java/org/apache/impala/catalog/KuduColumn.java
+++ b/fe/src/main/java/org/apache/impala/catalog/KuduColumn.java
@@ -72,7 +72,7 @@ public class KuduColumn extends Column {
 
   public static KuduColumn fromColumnSchema(ColumnSchema colSchema, int position)
       throws ImpalaRuntimeException {
-    Type type = KuduUtil.toImpalaType(colSchema.getType());
+    Type type = KuduUtil.toImpalaType(colSchema.getType(), colSchema.getTypeAttributes());
     Object defaultValue = colSchema.getDefaultValue();
     LiteralExpr defaultValueExpr = null;
     if (defaultValue != null) {

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/fe/src/main/java/org/apache/impala/planner/KuduScanNode.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/planner/KuduScanNode.java b/fe/src/main/java/org/apache/impala/planner/KuduScanNode.java
index 390592e..a02b49b 100644
--- a/fe/src/main/java/org/apache/impala/planner/KuduScanNode.java
+++ b/fe/src/main/java/org/apache/impala/planner/KuduScanNode.java
@@ -162,7 +162,8 @@ public class KuduScanNode extends ScanNode {
             "outdated and need to be refreshed.");
       }
 
-      Type kuduColType = KuduUtil.toImpalaType(kuduCol.getType());
+      Type kuduColType =
+          KuduUtil.toImpalaType(kuduCol.getType(), kuduCol.getTypeAttributes());
       if (!colType.equals(kuduColType)) {
         throw new ImpalaRuntimeException("Column '" + colName + "' is type " +
             kuduColType.toSql() + " but Impala expected " + colType.toSql() +

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/fe/src/main/java/org/apache/impala/planner/RuntimeFilterGenerator.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/planner/RuntimeFilterGenerator.java b/fe/src/main/java/org/apache/impala/planner/RuntimeFilterGenerator.java
index 5368b5f..89f14d1 100644
--- a/fe/src/main/java/org/apache/impala/planner/RuntimeFilterGenerator.java
+++ b/fe/src/main/java/org/apache/impala/planner/RuntimeFilterGenerator.java
@@ -699,6 +699,8 @@ public final class RuntimeFilterGenerator {
         continue;
       } else if (scanNode instanceof KuduScanNode) {
         if (filter.getType() != TRuntimeFilterType.MIN_MAX) continue;
+        // TODO: IMPALA-6533: Support Kudu Decimal Min/Max Filters
+        if (targetExpr.getType().isDecimal()) continue;
         SlotRef slotRef = targetExpr.unwrapSlotRef(true);
         // Kudu only supports targeting a single column, not general exprs, so the target
         // must be a SlotRef pointing to a column. We can allow implicit integer casts

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/fe/src/main/java/org/apache/impala/service/KuduCatalogOpExecutor.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/service/KuduCatalogOpExecutor.java b/fe/src/main/java/org/apache/impala/service/KuduCatalogOpExecutor.java
index c81aca4..0ce0cf9 100644
--- a/fe/src/main/java/org/apache/impala/service/KuduCatalogOpExecutor.java
+++ b/fe/src/main/java/org/apache/impala/service/KuduCatalogOpExecutor.java
@@ -48,6 +48,7 @@ import org.apache.kudu.client.KuduClient;
 import org.apache.kudu.client.KuduException;
 import org.apache.kudu.client.PartialRow;
 import org.apache.kudu.client.RangePartitionBound;
+import org.apache.kudu.util.DecimalUtil;
 import org.apache.log4j.Logger;
 
 import com.google.common.base.Preconditions;
@@ -113,8 +114,8 @@ public class KuduCatalogOpExecutor {
       csb.nullable(!isKey);
     }
     if (column.isSetDefault_value()) {
-      csb.defaultValue(KuduUtil.getKuduDefaultValue(column.getDefault_value(), kuduType,
-            column.getColumnName()));
+      csb.defaultValue(KuduUtil.getKuduDefaultValue(
+          column.getDefault_value(), type, column.getColumnName()));
     }
     if (column.isSetBlock_size()) csb.desiredBlockSize(column.getBlock_size());
     if (column.isSetEncoding()) {
@@ -123,6 +124,10 @@ public class KuduCatalogOpExecutor {
     if (column.isSetCompression()) {
       csb.compressionAlgorithm(KuduUtil.fromThrift(column.getCompression()));
     }
+    if (type.isDecimal()) {
+      csb.typeAttributes(
+          DecimalUtil.typeAttributes(type.getPrecision(), type.getDecimalDigits()));
+    }
     return csb.build();
   }
 
@@ -267,7 +272,8 @@ public class KuduCatalogOpExecutor {
               "Error loading Kudu table: Impala does not support column names that " +
               "differ only in casing '%s'", colSchema.getName()));
         }
-        Type type = KuduUtil.toImpalaType(colSchema.getType());
+        Type type =
+            KuduUtil.toImpalaType(colSchema.getType(), colSchema.getTypeAttributes());
         cols.add(new FieldSchema(colSchema.getName(), type.toSql().toLowerCase(), null));
       }
     } catch (Exception e) {
@@ -446,10 +452,9 @@ public class KuduCatalogOpExecutor {
     AlterTableOptions alterTableOptions = new AlterTableOptions();
 
     if (newCol.isSetDefault_value()) {
-      org.apache.kudu.Type kuduType =
-          KuduUtil.fromImpalaType(Type.fromThrift(newCol.getColumnType()));
+      Type type = Type.fromThrift(newCol.getColumnType());
       Object defaultValue = KuduUtil.getKuduDefaultValue(
-          newCol.getDefault_value(), kuduType, newCol.getColumnName());
+          newCol.getDefault_value(), type, newCol.getColumnName());
       if (defaultValue == null) {
         alterTableOptions.removeDefault(kuduColName);
       } else {

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/fe/src/main/java/org/apache/impala/util/KuduUtil.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/util/KuduUtil.java b/fe/src/main/java/org/apache/impala/util/KuduUtil.java
index 4df8005..07378a9 100644
--- a/fe/src/main/java/org/apache/impala/util/KuduUtil.java
+++ b/fe/src/main/java/org/apache/impala/util/KuduUtil.java
@@ -19,6 +19,8 @@ package org.apache.impala.util;
 
 import static java.lang.String.format;
 
+import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.util.List;
 import java.util.Map;
 
@@ -48,6 +50,7 @@ import org.apache.impala.thrift.THdfsCompression;
 import org.apache.kudu.ColumnSchema;
 import org.apache.kudu.ColumnSchema.CompressionAlgorithm;
 import org.apache.kudu.ColumnSchema.Encoding;
+import org.apache.kudu.ColumnTypeAttributes;
 import org.apache.kudu.Schema;
 import org.apache.kudu.client.KuduClient;
 import org.apache.kudu.client.KuduClient.KuduClientBuilder;
@@ -104,8 +107,7 @@ public class KuduUtil {
       String colName = rangePartitionColumns.get(i);
       ColumnSchema col = schema.getColumn(colName);
       Preconditions.checkNotNull(col);
-      setKey(col.getType(), boundaryValues.get(i), schema.getColumnIndex(colName),
-          colName, bound);
+      setKey(col, boundaryValues.get(i), schema.getColumnIndex(colName), bound);
     }
     return bound;
   }
@@ -140,10 +142,12 @@ public class KuduUtil {
    * Sets the value 'boundaryVal' in 'key' at 'pos'. Checks if 'boundaryVal' has the
    * expected data type.
    */
-  private static void setKey(org.apache.kudu.Type type, TExpr boundaryVal, int pos,
-      String colName, PartialRow key) throws ImpalaRuntimeException {
+  private static void setKey(ColumnSchema col, TExpr boundaryVal, int pos, PartialRow key)
+      throws ImpalaRuntimeException {
     Preconditions.checkState(boundaryVal.getNodes().size() == 1);
     TExprNode literal = boundaryVal.getNodes().get(0);
+    String colName = col.getName();
+    org.apache.kudu.Type type = col.getType();
     switch (type) {
       case INT8:
         checkCorrectType(literal.isSetInt_literal(), type, colName, literal);
@@ -169,6 +173,12 @@ public class KuduUtil {
         checkCorrectType(literal.isSetInt_literal(), type, colName, literal);
         key.addLong(pos, literal.getInt_literal().getValue());
         break;
+      case DECIMAL:
+        checkCorrectType(literal.isSetDecimal_literal(), type, colName, literal);
+        BigInteger unscaledVal = new BigInteger(literal.getDecimal_literal().getValue());
+        int scale = col.getTypeAttributes().getScale();
+        key.addDecimal(pos, new BigDecimal(unscaledVal, scale));
+        break;
       default:
         throw new ImpalaRuntimeException("Key columns not supported for type: "
             + type.toString());
@@ -177,15 +187,17 @@ public class KuduUtil {
 
   /**
    * Returns the actual value of the specified defaultValue literal. The returned type is
-   * the value type stored by Kudu for the column. E.g. if 'type' is 'INT8', the returned
-   * value is a Java byte, and if 'type' is 'UNIXTIME_MICROS', the returned value is
+   * the value type stored by Kudu for the column. For example, The `impalaType` is
+   * translated to a Kudu Type 'type' and if 'type' is 'INT8', the returned
+   * value is a Java byte, or if 'type' is 'UNIXTIME_MICROS', the returned value is
    * a Java long.
    */
-  public static Object getKuduDefaultValue(TExpr defaultValue,
-      org.apache.kudu.Type type, String colName) throws ImpalaRuntimeException {
+  public static Object getKuduDefaultValue(
+      TExpr defaultValue, Type impalaType, String colName) throws ImpalaRuntimeException {
     Preconditions.checkState(defaultValue.getNodes().size() == 1);
     TExprNode literal = defaultValue.getNodes().get(0);
     if (literal.getNode_type() == TExprNodeType.NULL_LITERAL) return null;
+    org.apache.kudu.Type type = KuduUtil.fromImpalaType(impalaType);
     switch (type) {
       case INT8:
         checkCorrectType(literal.isSetInt_literal(), type, colName, literal);
@@ -214,6 +226,10 @@ public class KuduUtil {
       case UNIXTIME_MICROS:
         checkCorrectType(literal.isSetInt_literal(), type, colName, literal);
         return literal.getInt_literal().getValue();
+      case DECIMAL:
+        checkCorrectType(literal.isSetDecimal_literal(), type, colName, literal);
+        BigInteger unscaledVal = new BigInteger(literal.getDecimal_literal().getValue());
+        return new BigDecimal(unscaledVal, impalaType.getDecimalDigits());
       default:
         throw new ImpalaRuntimeException("Unsupported value for column type: " +
             type.toString());
@@ -392,13 +408,13 @@ public class KuduUtil {
       case DOUBLE: return org.apache.kudu.Type.DOUBLE;
       case FLOAT: return org.apache.kudu.Type.FLOAT;
       case TIMESTAMP: return org.apache.kudu.Type.UNIXTIME_MICROS;
-        /* Fall through below */
+      case DECIMAL: return org.apache.kudu.Type.DECIMAL;
+      /* Fall through below */
       case INVALID_TYPE:
       case NULL_TYPE:
       case BINARY:
       case DATE:
       case DATETIME:
-      case DECIMAL:
       case CHAR:
       case VARCHAR:
       default:
@@ -407,8 +423,8 @@ public class KuduUtil {
     }
   }
 
-  public static Type toImpalaType(org.apache.kudu.Type t)
-      throws ImpalaRuntimeException {
+  public static Type toImpalaType(org.apache.kudu.Type t,
+      ColumnTypeAttributes typeAttributes) throws ImpalaRuntimeException {
     switch (t) {
       case BOOL: return Type.BOOLEAN;
       case DOUBLE: return Type.DOUBLE;
@@ -419,6 +435,9 @@ public class KuduUtil {
       case INT64: return Type.BIGINT;
       case STRING: return Type.STRING;
       case UNIXTIME_MICROS: return Type.TIMESTAMP;
+      case DECIMAL:
+        return ScalarType.createDecimalType(
+            typeAttributes.getPrecision(), typeAttributes.getScale());
       default:
         throw new ImpalaRuntimeException(String.format(
             "Kudu type '%s' is not supported in Impala", t.getName()));

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
index 56f81e3..ce49828 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeDDLTest.java
@@ -1792,6 +1792,10 @@ public class AnalyzeDDLTest extends FrontendTestBase {
         "left join functional.alltypes b " +
         "on b.timestamp_col between a.timestamp_col and a.timestamp_col) " +
         "select a.timestamp_col, a.year from tmp a");
+    // CTAS into Kudu with decimal type
+    AnalyzesOk("create table t primary key (id) partition by hash partitions 3" +
+        " stored as kudu as select c1 as id from functional.decimal_tiny");
+
     // CTAS in an external Kudu table
     AnalysisError("create external table t stored as kudu " +
         "tblproperties('kudu.table_name'='t') as select id, int_col from " +
@@ -1806,9 +1810,6 @@ public class AnalyzeDDLTest extends FrontendTestBase {
         " stored as kudu as select vc from functional.chars_tiny",
         "Cannot create table 't': Type VARCHAR(32) is not supported in Kudu");
     AnalysisError("create table t primary key (id) partition by hash partitions 3" +
-        " stored as kudu as select c1 as id from functional.decimal_tiny",
-        "Cannot create table 't': Type DECIMAL(10,4) is not supported in Kudu");
-    AnalysisError("create table t primary key (id) partition by hash partitions 3" +
         " stored as kudu as select id, s from functional.complextypes_fileformat",
         "Expr 's' in select list returns a complex type 'STRUCT<f1:STRING,f2:INT>'.\n" +
         "Only scalar types are allowed in the select list.");
@@ -2212,6 +2213,9 @@ public class AnalyzeDDLTest extends FrontendTestBase {
     AnalyzesOk("alter table functional_kudu.testtbl add columns (a1 tinyint null, a2 " +
         "smallint null, a3 int null, a4 bigint null, a5 string null, a6 float null, " +
         "a7 double null, a8 boolean null comment 'boolean')");
+    // Decimal types
+    AnalyzesOk("alter table functional_kudu.testtbl add columns (d1 decimal null, d2 " +
+        "decimal(9, 2) null, d3 decimal(15, 15) null, d4 decimal(38, 0) null)");
     // Complex types
     AnalysisError("alter table functional_kudu.testtbl add columns ( "+
         "a struct<f1:int>)", "Kudu tables do not support complex types: " +
@@ -2225,6 +2229,8 @@ public class AnalyzeDDLTest extends FrontendTestBase {
         "default 10)");
     AnalyzesOk("alter table functional_kudu.testtbl add columns (a1 int null " +
         "default 10)");
+    AnalyzesOk("alter table functional_kudu.testtbl add columns (d1 decimal(9, 2) null " +
+        "default 99.99)");
     // Other Kudu column options
     AnalyzesOk("alter table functional_kudu.testtbl add columns (a int encoding rle)");
     AnalyzesOk("alter table functional_kudu.testtbl add columns (a int compression lz4)");
@@ -2477,8 +2483,7 @@ public class AnalyzeDDLTest extends FrontendTestBase {
         "in Kudu tables.");
 
     // Test unsupported Kudu types
-    List<String> unsupportedTypes = Lists.newArrayList(
-        "DECIMAL(9,0)", "VARCHAR(20)", "CHAR(20)",
+    List<String> unsupportedTypes = Lists.newArrayList("VARCHAR(20)", "CHAR(20)",
         "STRUCT<f1:INT,f2:STRING>", "ARRAY<INT>", "MAP<STRING,STRING>");
     for (String t: unsupportedTypes) {
       String expectedError = String.format(
@@ -2529,7 +2534,8 @@ public class AnalyzeDDLTest extends FrontendTestBase {
     AnalyzesOk("create table tab (x int primary key, i1 tinyint default null, " +
         "i2 smallint default null, i3 int default null, i4 bigint default null, " +
         "vals string default null, valf float default null, vald double default null, " +
-        "valb boolean default null) partition by hash (x) partitions 3 stored as kudu");
+        "valb boolean default null, valdec decimal(10, 5) default null) " +
+        "partition by hash (x) partitions 3 stored as kudu");
     // Use NULL as a default value on a non-nullable column
     AnalysisError("create table tab (x int primary key, y int not null default null) " +
         "partition by hash (x) partitions 3 stored as kudu", "Default value of NULL " +
@@ -2561,6 +2567,7 @@ public class AnalyzeDDLTest extends FrontendTestBase {
         "i3 int default 100, i4 bigint default 1000, vals string default 'test', " +
         "valf float default cast(1.2 as float), vald double default " +
         "cast(3.1452 as double), valb boolean default true, " +
+        "valdec decimal(10, 5) default 3.14159, " +
         "primary key (i1, i2, i3, i4, vals)) partition by hash (i1) partitions 3 " +
         "stored as kudu");
     AnalyzesOk("create table tab (i int primary key default 1+1+1) " +

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/testdata/datasets/functional/functional_schema_template.sql
----------------------------------------------------------------------
diff --git a/testdata/datasets/functional/functional_schema_template.sql b/testdata/datasets/functional/functional_schema_template.sql
index f4b6b34..8db806a 100644
--- a/testdata/datasets/functional/functional_schema_template.sql
+++ b/testdata/datasets/functional/functional_schema_template.sql
@@ -1726,6 +1726,23 @@ ${IMPALA_HOME}/testdata/data/decimal_tbl.txt /test-warehouse/decimal_tbl/d6=1/
 ---- DEPENDENT_LOAD
 INSERT OVERWRITE TABLE {db_name}{db_suffix}.{table_name} partition(d6)
 select * from functional.{table_name};
+---- CREATE_KUDU
+DROP TABLE IF EXISTS {db_name}{db_suffix}.{table_name};
+CREATE TABLE {db_name}{db_suffix}.{table_name} (
+  d1 DECIMAL,
+  d2 DECIMAL(10, 0),
+  d3 DECIMAL(20, 10),
+  d4 DECIMAL(38, 38),
+  d5 DECIMAL(10, 5),
+  d6 DECIMAL(9, 0),
+  PRIMARY KEY (d1, d2, d3, d4, d5, d6)
+)
+PARTITION BY HASH PARTITIONS 3
+STORED AS KUDU;
+---- DEPENDENT_LOAD_KUDU
+INSERT into TABLE {db_name}{db_suffix}.{table_name}
+SELECT d1, d2, d3, d4, d5, d6
+FROM {db_name}.{table_name};
 ====
 ---- DATASET
 functional
@@ -1743,6 +1760,20 @@ ${IMPALA_HOME}/testdata/data/decimal-tiny.txt /test-warehouse/decimal_tiny/
 ---- DEPENDENT_LOAD
 INSERT OVERWRITE TABLE {db_name}{db_suffix}.{table_name}
 select * from functional.{table_name};
+---- CREATE_KUDU
+DROP TABLE IF EXISTS {db_name}{db_suffix}.{table_name};
+CREATE TABLE {db_name}{db_suffix}.{table_name} (
+  c1 DECIMAL(10, 4),
+  c2 DECIMAL(15, 5),
+  c3 DECIMAL(1, 1),
+  PRIMARY KEY (c1, c2, c3)
+)
+PARTITION BY HASH PARTITIONS 3
+STORED AS KUDU;
+---- DEPENDENT_LOAD_KUDU
+INSERT into TABLE {db_name}{db_suffix}.{table_name}
+SELECT c1, c2, c3
+FROM {db_name}.{table_name};
 ====
 ---- DATASET
 functional

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/testdata/datasets/functional/schema_constraints.csv
----------------------------------------------------------------------
diff --git a/testdata/datasets/functional/schema_constraints.csv b/testdata/datasets/functional/schema_constraints.csv
index 355e9b1..ef65b9a 100644
--- a/testdata/datasets/functional/schema_constraints.csv
+++ b/testdata/datasets/functional/schema_constraints.csv
@@ -132,6 +132,8 @@ table_name:decimal_tbl, constraint:restrict_to, table_format:text/none/none
 table_name:decimal_tiny, constraint:restrict_to, table_format:text/none/none
 table_name:decimal_tbl, constraint:restrict_to, table_format:parquet/none/none
 table_name:decimal_tiny, constraint:restrict_to, table_format:parquet/none/none
+table_name:decimal_tbl, constraint:restrict_to, table_format:kudu/none/none
+table_name:decimal_tiny, constraint:restrict_to, table_format:kudu/none/none
 
 table_name:avro_decimal_tbl, constraint:restrict_to, table_format:avro/snap/block
 
@@ -186,6 +188,8 @@ table_name:tinyinttable, constraint:only, table_format:kudu/none/none
 table_name:zipcode_incomes, constraint:only, table_format:kudu/none/none
 table_name:nulltable, constraint:only, table_format:kudu/none/none
 table_name:nullescapedtable, constraint:only, table_format:kudu/none/none
+table_name:decimal_tbl, constraint:only, table_format:kudu/none/none
+table_name:decimal_tiny, constraint:only, table_format:kudu/none/none
 
 # Skipping header lines is only effective with text tables
 table_name:table_with_header, constraint:restrict_to, table_format:text/none/none

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/testdata/workloads/functional-query/queries/QueryTest/kudu_create.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-query/queries/QueryTest/kudu_create.test b/testdata/workloads/functional-query/queries/QueryTest/kudu_create.test
index f6e16e1..24dfdf1 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/kudu_create.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/kudu_create.test
@@ -129,7 +129,9 @@ INT,STRING,FLOAT,BIGINT
 create table tbl_with_null_defaults (x int primary key, i1 tinyint default null,
   i2 smallint default null, i3 int default null, i4 bigint default null,
   vals string default null, valf float default null, vald double default null,
-  valb boolean default null) partition by hash (x) partitions 3 stored as kudu
+  valb boolean default null, valdec4 decimal(9) default null,
+  valdec8 decimal(18) default null, valdec16 decimal(38) default null)
+  partition by hash (x) partitions 3 stored as kudu
 ---- RESULTS
 ====
 ---- QUERY
@@ -138,11 +140,11 @@ insert into tbl_with_null_defaults (x) values (1);
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-X, I1, I2, I3, I4, VALS, VALF, VALD, VALB
+X, I1, I2, I3, I4, VALS, VALF, VALD, VALB, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tbl_with_null_defaults
-1,NULL,NULL,NULL,NULL,'NULL',NULL,NULL,NULL
+1,NULL,NULL,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,TINYINT,SMALLINT,INT,BIGINT,STRING,FLOAT,DOUBLE,BOOLEAN
+INT,TINYINT,SMALLINT,INT,BIGINT,STRING,FLOAT,DOUBLE,BOOLEAN,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # Overlapping ranges are rejected by the Kudu client
@@ -287,4 +289,30 @@ select * from unpartitioned_kudu_table2
 ID
 ---- TYPES
 INT
+====
+---- QUERY
+# Creates a Kudu table with decimal columns and primary key
+create table create_decimal
+(
+ decimal_4 decimal(9, 9),
+ decimal_8 decimal(18, 2) not null default 100.00,
+ decimal_16 decimal(38, 0) null,
+ primary key (decimal_4))
+stored as kudu;
+---- RESULTS
+====
+---- QUERY
+# Create as select table with decimal columns and primary key
+create table ctas_decimal primary key (d1,d2,d3)
+stored as kudu
+as select * from functional.decimal_tbl;
+select * from ctas_decimal;
+---- RESULTS
+1234,2222,1.2345678900,0.12345678900000000000000000000000000000,12345.78900,1
+2345,111,12.3456789000,0.12345678900000000000000000000000000000,3.14100,1
+12345,333,123.4567890000,0.12345678900000000000000000000000000000,11.22000,1
+12345,333,1234.5678900000,0.12345678900000000000000000000000000000,0.10000,1
+132842,333,12345.6789000000,0.12345678900000000000000000000000000000,0.77889,1
+---- TYPES
+DECIMAL,DECIMAL,DECIMAL,DECIMAL,DECIMAL,DECIMAL
 ====
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/testdata/workloads/functional-query/queries/QueryTest/kudu_delete.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-query/queries/QueryTest/kudu_delete.test b/testdata/workloads/functional-query/queries/QueryTest/kudu_delete.test
index 7094c59..3abcdab 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/kudu_delete.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/kudu_delete.test
@@ -2,23 +2,25 @@
 ---- QUERY
 create table tdata
   (id int primary key, valf float null, vali bigint null, valv string null,
-   valb boolean null, valt tinyint null, vals smallint null, vald double null)
+   valb boolean null, valt tinyint null, vals smallint null, vald double null,
+   valdec4 decimal(9,9) null, valdec8 decimal(18,2) null,
+   valdec16 decimal(38, 0) null)
   PARTITION BY RANGE (PARTITION VALUES < 100, PARTITION 100 <= VALUES < 1000,
   PARTITION 1000 <= VALUES <= 10000) STORED AS KUDU
 ---- RESULTS
 ====
 ---- QUERY
 insert into table tdata values
-(1, 1.0, 1, 'one', true, 1, 1, 1),
-(2, -2, 20, 'two', false, 0, 1, NULL),
-(3, 0, NULL, 'three', false, 10, 20, 30),
-(4, 5, 6, 'four', true, 7, 8, 9),
-(5, 0, 10, 'five', NULL, 15, 20, 25),
-(6, 9, 12, 'six', true, -1, -2, cast('inf' as double)),
-(7, NULL, 7, 'seven', false, 77, 777, NULL),
-(8, 0, 80, NULL, true, 10, 11, 12),
-(9, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-(127, 1, 2, '127', false, 3, 4, 5)
+(1, 1.0, 1, 'one', true, 1, 1, 1, 0.000000001, 1.11, 1),
+(2, -2, 20, 'two', false, 0, 1, NULL, 0.000000002, 2.22, 2),
+(3, 0, NULL, 'three', false, 10, 20, 30, 0.000000040, 50.00, 60),
+(4, 5, 6, 'four', true, 7, 8, 9, 0.000000010, 11.11, 12),
+(5, 0, 10, 'five', NULL, 15, 20, 25, 0.000000030, 35.35, 40),
+(6, 9, 12, 'six', true, -1, -2, cast('inf' as double), -0.000000001, -1.11, -1),
+(7, NULL, 7, 'seven', false, 77, 777, NULL, NULL, NULL, NULL),
+(8, 0, 80, NULL, true, 10, 11, 12, 0.000000013, 0.14, 15),
+(9, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(127, 1, 2, '127', false, 3, 4, 5, 0.000000000, 0.00, 0)
 ---- RESULTS
 : 10
 ====
@@ -29,19 +31,19 @@ delete from tdata where id = 1
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-4,5,6,'four',true,7,8,9
-5,0,10,'five',NULL,15,20,25
-6,9,12,'six',true,-1,-2,Infinity
-7,NULL,7,'seven',false,77,777,NULL
-8,0,80,'NULL',true,10,11,12
-9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-127,1,2,'127',false,3,4,5
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+4,5,6,'four',true,7,8,9,0.000000010,11.11,12
+5,0,10,'five',NULL,15,20,25,0.000000030,35.35,40
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+7,NULL,7,'seven',false,77,777,NULL,NULL,NULL,NULL
+8,0,80,'NULL',true,10,11,12,0.000000013,0.14,15
+9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL
+127,1,2,'127',false,3,4,5,0.000000000,0.00,0
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # predicate on key, NULL
@@ -50,19 +52,19 @@ delete from tdata where id is NULL
 NumModifiedRows: 0
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-4,5,6,'four',true,7,8,9
-5,0,10,'five',NULL,15,20,25
-6,9,12,'six',true,-1,-2,Infinity
-7,NULL,7,'seven',false,77,777,NULL
-8,0,80,'NULL',true,10,11,12
-9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-127,1,2,'127',false,3,4,5
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+4,5,6,'four',true,7,8,9,0.000000010,11.11,12
+5,0,10,'five',NULL,15,20,25,0.000000030,35.35,40
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+7,NULL,7,'seven',false,77,777,NULL,NULL,NULL,NULL
+8,0,80,'NULL',true,10,11,12,0.000000013,0.14,15
+9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL
+127,1,2,'127',false,3,4,5,0.000000000,0.00,0
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # predicate on key, nothing is deleted
@@ -71,19 +73,19 @@ delete from tdata where id = 10
 NumModifiedRows: 0
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-4,5,6,'four',true,7,8,9
-5,0,10,'five',NULL,15,20,25
-6,9,12,'six',true,-1,-2,Infinity
-7,NULL,7,'seven',false,77,777,NULL
-8,0,80,'NULL',true,10,11,12
-9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-127,1,2,'127',false,3,4,5
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+4,5,6,'four',true,7,8,9,0.000000010,11.11,12
+5,0,10,'five',NULL,15,20,25,0.000000030,35.35,40
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+7,NULL,7,'seven',false,77,777,NULL,NULL,NULL,NULL
+8,0,80,'NULL',true,10,11,12,0.000000013,0.14,15
+9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL
+127,1,2,'127',false,3,4,5,0.000000000,0.00,0
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # predicate on key, boundary value
@@ -92,18 +94,18 @@ delete from tdata where id = max_tinyint()
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-4,5,6,'four',true,7,8,9
-5,0,10,'five',NULL,15,20,25
-6,9,12,'six',true,-1,-2,Infinity
-7,NULL,7,'seven',false,77,777,NULL
-8,0,80,'NULL',true,10,11,12
-9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+4,5,6,'four',true,7,8,9,0.000000010,11.11,12
+5,0,10,'five',NULL,15,20,25,0.000000030,35.35,40
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+7,NULL,7,'seven',false,77,777,NULL,NULL,NULL,NULL
+8,0,80,'NULL',true,10,11,12,0.000000013,0.14,15
+9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # compound predicate on key
@@ -112,17 +114,17 @@ delete from tdata where id > 6 and id < 8
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-4,5,6,'four',true,7,8,9
-5,0,10,'five',NULL,15,20,25
-6,9,12,'six',true,-1,-2,Infinity
-8,0,80,'NULL',true,10,11,12
-9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+4,5,6,'four',true,7,8,9,0.000000010,11.11,12
+5,0,10,'five',NULL,15,20,25,0.000000030,35.35,40
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+8,0,80,'NULL',true,10,11,12,0.000000013,0.14,15
+9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # predicate on key, multiple rows
@@ -131,23 +133,23 @@ delete from tdata where id % 4 = 0
 NumModifiedRows: 2
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-5,0,10,'five',NULL,15,20,25
-6,9,12,'six',true,-1,-2,Infinity
-9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+5,0,10,'five',NULL,15,20,25,0.000000030,35.35,40
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # insert new values, including some that were previously deleted
 insert into table tdata values
-(10, 20, 30, 'ten', true, 40, 50, 60),
-(1, 1.0, 1, 'one', true, 1, 1, 1),
-(11, -11, 11, 'eleven', false, 1, 11, 111),
-(8, 0, 80, NULL, true, 10, 11, 12)
+(10, 20, 30, 'ten', true, 40, 50, 60, 0.000000070, 80.80, 90),
+(1, 1.0, 1, 'one', true, 1, 1, 1, 0.000000001, 1.11, 1),
+(11, -11, 11, 'eleven', false, 1, 11, 111, 0.000000011, 11.00, 11),
+(8, 0, 80, NULL, true, 10, 11, 12, 0.000000013, 0.14, 15)
 ====
 ---- QUERY
 # single row, predicate on non-key
@@ -156,18 +158,18 @@ delete from tdata where valv = 'five'
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-6,9,12,'six',true,-1,-2,Infinity
-9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-10,20,30,'ten',true,40,50,60
-1,1.0,1,'one',true,1,1,1
-11,-11,11,'eleven',false,1,11,111
-8,0,80,'NULL',true,10,11,12
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+9,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL
+10,20,30,'ten',true,40,50,60,0.000000070,80.80,90
+1,1.0,1,'one',true,1,1,1,0.000000001,1.11,1
+11,-11,11,'eleven',false,1,11,111,0.000000011,11.00,11
+8,0,80,'NULL',true,10,11,12,0.000000013,0.14,15
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # predicate on non-key, NULL
@@ -176,17 +178,17 @@ delete from tdata where valb is NULL
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-6,9,12,'six',true,-1,-2,Infinity
-10,20,30,'ten',true,40,50,60
-1,1.0,1,'one',true,1,1,1
-11,-11,11,'eleven',false,1,11,111
-8,0,80,'NULL',true,10,11,12
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+10,20,30,'ten',true,40,50,60,0.000000070,80.80,90
+1,1.0,1,'one',true,1,1,1,0.000000001,1.11,1
+11,-11,11,'eleven',false,1,11,111,0.000000011,11.00,11
+8,0,80,'NULL',true,10,11,12,0.000000013,0.14,15
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # predicate on non-key, nothing is deleted
@@ -195,17 +197,17 @@ delete from tdata where vals = -100
 NumModifiedRows: 0
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-6,9,12,'six',true,-1,-2,Infinity
-10,20,30,'ten',true,40,50,60
-1,1.0,1,'one',true,1,1,1
-11,-11,11,'eleven',false,1,11,111
-8,0,80,'NULL',true,10,11,12
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+10,20,30,'ten',true,40,50,60,0.000000070,80.80,90
+1,1.0,1,'one',true,1,1,1,0.000000001,1.11,1
+11,-11,11,'eleven',false,1,11,111,0.000000011,11.00,11
+8,0,80,'NULL',true,10,11,12,0.000000013,0.14,15
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # predicate on non-key, compound predicate
@@ -214,16 +216,16 @@ delete from tdata where valf = 0 and vali = 80
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-3,0,NULL,'three',false,10,20,30
-6,9,12,'six',true,-1,-2,Infinity
-10,20,30,'ten',true,40,50,60
-1,1.0,1,'one',true,1,1,1
-11,-11,11,'eleven',false,1,11,111
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+10,20,30,'ten',true,40,50,60,0.000000070,80.80,90
+1,1.0,1,'one',true,1,1,1,0.000000001,1.11,1
+11,-11,11,'eleven',false,1,11,111,0.000000011,11.00,11
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # predicate on non-key, multiple rows
@@ -232,14 +234,14 @@ delete from tdata where vals % 10 = 0
 NumModifiedRows: 2
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-6,9,12,'six',true,-1,-2,Infinity
-1,1.0,1,'one',true,1,1,1
-11,-11,11,'eleven',false,1,11,111
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+1,1.0,1,'one',true,1,1,1,0.000000001,1.11,1
+11,-11,11,'eleven',false,1,11,111,0.000000011,11.00,11
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # 'from' syntax - the join results in four deletes, 3 of which fail
@@ -248,13 +250,13 @@ delete a from tdata a, tdata b where a.id = 11
 NumModifiedRows: 1
 NumRowErrors: 3
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-6,9,12,'six',true,-1,-2,Infinity
-1,1.0,1,'one',true,1,1,1
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+1,1.0,1,'one',true,1,1,1,0.000000001,1.11,1
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # Try to delete a row with a primary key value that is not covered by the existing range
@@ -264,18 +266,56 @@ delete from tdata where id = 10001
 NumModifiedRows: 0
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-2,-2,20,'two',false,0,1,NULL
-6,9,12,'six',true,-1,-2,Infinity
-1,1.0,1,'one',true,1,1,1
+2,-2,20,'two',false,0,1,NULL,0.000000002,2.22,2
+6,9,12,'six',true,-1,-2,Infinity,-0.000000001,-1.11,-1
+1,1.0,1,'one',true,1,1,1,0.000000001,1.11,1
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
+====
+---- QUERY
+# Add a couple more rows back
+insert into table tdata values
+(3, 0, NULL, 'three', false, 10, 20, 30, 0.000000040, 50.00, 60),
+(4, 5, 6, 'four', true, 7, 8, 9, 0.000000010, 11.11, 12),
+(5, 0, 10, 'five', NULL, 15, 20, 25, 0.000000030, 35.35, 40)
+---- RESULTS
+: 3
+====
+---- QUERY
+# predicate on decimal, multiple rows
+delete from tdata where valdec8 < 11.11
+---- RUNTIME_PROFILE
+NumModifiedRows: 3
+NumRowErrors: 0
+---- LABELS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
+---- DML_RESULTS: tdata
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+4,5,6,'four',true,7,8,9,0.000000010,11.11,12
+5,0,10,'five',NULL,15,20,25,0.000000030,35.35,40
+---- TYPES
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
+====
+---- QUERY
+# predicate on decimal, single row
+delete from tdata where valdec4 = 0.000000030
+---- RUNTIME_PROFILE
+NumModifiedRows: 1
+NumRowErrors: 0
+---- LABELS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
+---- DML_RESULTS: tdata
+3,0,NULL,'three',false,10,20,30,0.000000040,50.00,60
+4,5,6,'four',true,7,8,9,0.000000010,11.11,12
+---- TYPES
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 insert into tdata
 select cast(id + 100 as int), float_col, bigint_col, string_col, bool_col, tinyint_col,
-smallint_col, double_col
+smallint_col, double_col, NULL, NULL, NULL
 from functional_kudu.alltypes
 ---- RESULTS
 : 7300
@@ -287,13 +327,13 @@ NumRowErrors: 0
 # Test a larger DELETE
 delete from tdata where id > -1
 ---- RUNTIME_PROFILE
-NumModifiedRows: 7303
+NumModifiedRows: 7302
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 create table multiple_key_cols

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/testdata/workloads/functional-query/queries/QueryTest/kudu_describe.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-query/queries/QueryTest/kudu_describe.test b/testdata/workloads/functional-query/queries/QueryTest/kudu_describe.test
index 687ca31..daaa18f 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/kudu_describe.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/kudu_describe.test
@@ -45,3 +45,23 @@ NAME,TYPE,COMMENT,PRIMARY_KEY,NULLABLE,DEFAULT_VALUE,ENCODING,COMPRESSION,BLOCK_
 ---- TYPES
 STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING
 ====
+---- QUERY
+# Test decimal columns and primary key
+create table describe_decimal_test
+(
+ decimal_default decimal PRIMARY KEY,
+ decimal_4 decimal(9, 9) not null,
+ decimal_8 decimal(18, 2) not null default 100.00,
+ decimal_16 decimal(38, 0) null)
+stored as kudu;
+describe describe_decimal_test;
+---- LABELS
+NAME,TYPE,COMMENT,PRIMARY_KEY,NULLABLE,DEFAULT_VALUE,ENCODING,COMPRESSION,BLOCK_SIZE
+---- RESULTS
+'decimal_default','decimal(9,0)','','true','false','','AUTO_ENCODING','DEFAULT_COMPRESSION','0'
+'decimal_4','decimal(9,9)','','false','false','','AUTO_ENCODING','DEFAULT_COMPRESSION','0'
+'decimal_8','decimal(18,2)','','false','false','100.00','AUTO_ENCODING','DEFAULT_COMPRESSION','0'
+'decimal_16','decimal(38,0)','','false','true','','AUTO_ENCODING','DEFAULT_COMPRESSION','0'
+---- TYPES
+STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING,STRING
+====

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/testdata/workloads/functional-query/queries/QueryTest/kudu_insert.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-query/queries/QueryTest/kudu_insert.test b/testdata/workloads/functional-query/queries/QueryTest/kudu_insert.test
index 420e42c..6bba77a 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/kudu_insert.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/kudu_insert.test
@@ -3,7 +3,8 @@
 create table tdata
   (id int primary key, valf float null, vali bigint null, valv string null,
    valb boolean null, valt tinyint null, vals smallint null, vald double null,
-   ts timestamp)
+   ts timestamp, decimal4 decimal(9,9) null, decimal8 decimal(18,2) null,
+   decimal16 decimal(38, 0) null)
   PARTITION BY RANGE (PARTITION VALUES < 10, PARTITION 10 <= VALUES < 30,
   PARTITION 30 <= VALUES) STORED AS KUDU
 ---- RESULTS
@@ -11,30 +12,30 @@ create table tdata
 ---- QUERY
 # VALUES, single row, all target cols, no errors
 insert into tdata values (1, 1, 1, 'one', true, 1, 1, 1,
-  cast('1987-05-19 00:00:00' as timestamp))
+  cast('1987-05-19 00:00:00' as timestamp), 0.000000001, 1.00, 1)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-1,1,1,'one',true,1,1,1,1987-05-19 00:00:00
+1,1,1,'one',true,1,1,1,1987-05-19 00:00:00,0.000000001,1.00,1
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all target cols, NULL
-insert into tdata values (2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
+insert into tdata values (2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-1,1,1,'one',true,1,1,1,1987-05-19 00:00:00
-2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+1,1,1,'one',true,1,1,1,1987-05-19 00:00:00,0.000000001,1.00,1
+2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all target cols, boundary values. The timestamp value is the max
@@ -43,18 +44,19 @@ INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
 insert into tdata values
 (3, cast('nan' as float), max_bigint(), '', true, min_tinyint(), max_smallint(),
   cast('-inf' as double),
-  nanoseconds_add(cast('9999-12-31 23:59:59' as timestamp), 999999999))
+  nanoseconds_add(cast('9999-12-31 23:59:59' as timestamp), 999999999),
+  0.999999999, 9999999999999999.99, 99999999999999999999999999999999999999)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-1,1,1,'one',true,1,1,1,1987-05-19 00:00:00
-2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
-3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000
+1,1,1,'one',true,1,1,1,1987-05-19 00:00:00,0.000000001,1.00,1
+2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000,0.999999999,9999999999999999.99,99999999999999999999999999999999999999
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, subset of target cols
@@ -63,36 +65,36 @@ insert into tdata (valb, vald, id) values (true, 0, 4)
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-1,1,1,'one',true,1,1,1,1987-05-19 00:00:00
-2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
-3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000
-4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL
+1,1,1,'one',true,1,1,1,1987-05-19 00:00:00,0.000000001,1.00,1
+2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000,0.999999999,9999999999999999.99,99999999999999999999999999999999999999
+4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # VALUES, multiple rows, all target cols
 insert into tdata values
-(5, 5.0, 5, 'five', false, NULL, NULL, NULL, NULL),
-(6, 16, 60, '', true, 0, -1, -6, cast('2010-12-31 23:59:59' as timestamp)),
-(7, NULL, 10, NULL, false, max_tinyint(), -7, 2, cast('1400-01-01 00:00:00' as timestamp))
+(5, 5.0, 5, 'five', false, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(6, 16, 60, '', true, 0, -1, -6, cast('2010-12-31 23:59:59' as timestamp), -0.000000001, -1.00, -1),
+(7, NULL, 10, NULL, false, max_tinyint(), -7, 2, cast('1400-01-01 00:00:00' as timestamp), 0.000000000, 0.00, 0)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 3
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-1,1,1,'one',true,1,1,1,1987-05-19 00:00:00
-2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
-3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000
-4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL
-5,5.0,5,'five',false,NULL,NULL,NULL,NULL
-6,16,60,'',true,0,-1,-6,2010-12-31 23:59:59
-7,NULL,10,'NULL',false,127,-7,2,1400-01-01 00:00:00
+1,1,1,'one',true,1,1,1,1987-05-19 00:00:00,0.000000001,1.00,1
+2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000,0.999999999,9999999999999999.99,99999999999999999999999999999999999999
+4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL,NULL,NULL,NULL
+5,5.0,5,'five',false,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+6,16,60,'',true,0,-1,-6,2010-12-31 23:59:59,-0.000000001,-1.00,-1
+7,NULL,10,'NULL',false,127,-7,2,1400-01-01 00:00:00,0.000000000,0.00,0
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # VALUES, multiple rows, subset of cols
@@ -103,44 +105,44 @@ insert into tdata (valv, valf, vali, id) values
 NumModifiedRows: 2
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-1,1,1,'one',true,1,1,1,1987-05-19 00:00:00
-2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
-3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000
-4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL
-5,5.0,5,'five',false,NULL,NULL,NULL,NULL
-6,16,60,'',true,0,-1,-6,2010-12-31 23:59:59
-7,NULL,10,'NULL',false,127,-7,2,1400-01-01 00:00:00
-8,88,888,'eight',NULL,NULL,NULL,NULL,NULL
-9,-9,-99,'NULL',NULL,NULL,NULL,NULL,NULL
+1,1,1,'one',true,1,1,1,1987-05-19 00:00:00,0.000000001,1.00,1
+2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000,0.999999999,9999999999999999.99,99999999999999999999999999999999999999
+4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL,NULL,NULL,NULL
+5,5.0,5,'five',false,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+6,16,60,'',true,0,-1,-6,2010-12-31 23:59:59,-0.000000001,-1.00,-1
+7,NULL,10,'NULL',false,127,-7,2,1400-01-01 00:00:00,0.000000000,0.00,0
+8,88,888,'eight',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+9,-9,-99,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # SELECT, single row, all target cols
 insert into tdata
 select id, float_col, bigint_col, string_col, bool_col, tinyint_col, smallint_col,
-double_col, timestamp_col
+double_col, timestamp_col, NULL, NULL, NULL
 from functional.alltypes where id = 10
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-1,1,1,'one',true,1,1,1,1987-05-19 00:00:00
-2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
-3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000
-4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL
-5,5.0,5,'five',false,NULL,NULL,NULL,NULL
-6,16,60,'',true,0,-1,-6,2010-12-31 23:59:59
-7,NULL,10,'NULL',false,127,-7,2,1400-01-01 00:00:00
-8,88,888,'eight',NULL,NULL,NULL,NULL,NULL
-9,-9,-99,'NULL',NULL,NULL,NULL,NULL,NULL
-10,0,0,'0',true,0,0,0,2009-01-02 00:10:00.450000000
+1,1,1,'one',true,1,1,1,1987-05-19 00:00:00,0.000000001,1.00,1
+2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000,0.999999999,9999999999999999.99,99999999999999999999999999999999999999
+4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL,NULL,NULL,NULL
+5,5.0,5,'five',false,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+6,16,60,'',true,0,-1,-6,2010-12-31 23:59:59,-0.000000001,-1.00,-1
+7,NULL,10,'NULL',false,127,-7,2,1400-01-01 00:00:00,0.000000000,0.00,0
+8,88,888,'eight',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+9,-9,-99,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+10,0,0,'0',true,0,0,0,2009-01-02 00:10:00.450000000,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # SELECT, single row, subset of cols
@@ -151,21 +153,21 @@ from functional.alltypes where id = 11
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-1,1,1,'one',true,1,1,1,1987-05-19 00:00:00
-2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
-3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000
-4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL
-5,5.0,5,'five',false,NULL,NULL,NULL,NULL
-6,16,60,'',true,0,-1,-6,2010-12-31 23:59:59
-7,NULL,10,'NULL',false,127,-7,2,1400-01-01 00:00:00
-8,88,888,'eight',NULL,NULL,NULL,NULL,NULL
-9,-9,-99,'NULL',NULL,NULL,NULL,NULL,NULL
-10,0,0,'0',true,0,0,0,2009-01-02 00:10:00.450000000
-11,NULL,10,'NULL',false,NULL,NULL,10.1,2009-01-02 00:11:00.450000000
+1,1,1,'one',true,1,1,1,1987-05-19 00:00:00,0.000000001,1.00,1
+2,NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+3,NaN,9223372036854775807,'',true,-128,32767,-Infinity,9999-12-31 23:59:59.999999000,0.999999999,9999999999999999.99,99999999999999999999999999999999999999
+4,NULL,NULL,'NULL',true,NULL,NULL,0,NULL,NULL,NULL,NULL
+5,5.0,5,'five',false,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+6,16,60,'',true,0,-1,-6,2010-12-31 23:59:59,-0.000000001,-1.00,-1
+7,NULL,10,'NULL',false,127,-7,2,1400-01-01 00:00:00,0.000000000,0.00,0
+8,88,888,'eight',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+9,-9,-99,'NULL',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+10,0,0,'0',true,0,0,0,2009-01-02 00:10:00.450000000,NULL,NULL,NULL
+11,NULL,10,'NULL',false,NULL,NULL,10.1,2009-01-02 00:11:00.450000000,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 delete tdata
@@ -175,18 +177,18 @@ delete tdata
 # SELECT, multiple rows, all target cols
 insert into tdata
 select id, float_col, bigint_col, string_col, bool_col, tinyint_col, smallint_col,
-double_col, timestamp_col
+double_col, timestamp_col, NULL, NULL, NULL
 from functional.alltypes where id < 2
 ---- RUNTIME_PROFILE
 NumModifiedRows: 2
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-0,0,0,'0',true,0,0,0,2009-01-01 00:00:00
-1,1.100000023841858,10,'1',false,1,1,10.1,2009-01-01 00:01:00
+0,0,0,'0',true,0,0,0,2009-01-01 00:00:00,NULL,NULL,NULL
+1,1.100000023841858,10,'1',false,1,1,10.1,2009-01-01 00:01:00,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # SELECT, multiple rows, subset of cols
@@ -197,20 +199,20 @@ from functional.alltypes where id > 2 and id < 6
 NumModifiedRows: 3
 NumRowErrors: 0
 ---- LABELS
-ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS
+ID, VALF, VALI, VALV, VALB, VALT, VALS, VALD, TS, DECIMAL4, DECIMAL8, DECIMAL16
 ---- DML_RESULTS: tdata
-0,0,0,'0',true,0,0,0,2009-01-01 00:00:00
-1,1.100000023841858,10,'1',false,1,1,10.1,2009-01-01 00:01:00
-3,NULL,NULL,'NULL',NULL,3,3,30.3,2009-01-01 00:03:00.300000000
-4,NULL,NULL,'NULL',NULL,4,4,40.4,2009-01-01 00:04:00.600000000
-5,NULL,NULL,'NULL',NULL,5,5,50.5,2009-01-01 00:05:00.100000000
+0,0,0,'0',true,0,0,0,2009-01-01 00:00:00,NULL,NULL,NULL
+1,1.100000023841858,10,'1',false,1,1,10.1,2009-01-01 00:01:00,NULL,NULL,NULL
+3,NULL,NULL,'NULL',NULL,3,3,30.3,2009-01-01 00:03:00.300000000,NULL,NULL,NULL
+4,NULL,NULL,'NULL',NULL,4,4,40.4,2009-01-01 00:04:00.600000000,NULL,NULL,NULL
+5,NULL,NULL,'NULL',NULL,5,5,50.5,2009-01-01 00:05:00.100000000,NULL,NULL,NULL
 ---- TYPES
-INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP
+INT,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,TIMESTAMP,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # Make sure we can insert empty strings into string columns and that we can scan them
 # back.
-insert into tdata values (320, 2.0, 932, cast('' as string), false, 0, 0, 0, NULL)
+insert into tdata values (320, 2.0, 932, cast('' as string), false, 0, 0, 0, NULL, NULL, NULL, NULL)
 ---- RESULTS
 : 1
 ---- RUNTIME_PROFILE
@@ -226,7 +228,7 @@ INT,STRING,BOOLEAN
 ====
 ---- QUERY
 insert into tdata values
-(666, cast(1.2 as float), 43, cast('z' as string), true, 0, 0, 0, NULL)
+(666, cast(1.2 as float), 43, cast('z' as string), true, 0, 0, 0, NULL, NULL, NULL, NULL)
 ---- RESULTS
 : 1
 ---- RUNTIME_PROFILE
@@ -236,7 +238,7 @@ NumRowErrors: 0
 ---- QUERY
 # insert row with primary key that already exists
 insert into tdata values
-(666, cast(1.2 as float), 43, cast('z' as VARCHAR(20)), true, 0, 0, 0, NULL)
+(666, cast(1.2 as float), 43, cast('z' as VARCHAR(20)), true, 0, 0, 0, NULL, NULL, NULL, NULL)
 ---- RESULTS
 : 0
 ---- RUNTIME_PROFILE
@@ -319,7 +321,8 @@ NumRowErrors: 0
 # Table with default values
 create table tbl_with_defaults (a int primary key, b int null default 10,
   c int not null default 100, d int default 1000, e int null, f int not null,
-  g string default 'test', h boolean default true) partition by hash (a)
+  g string default 'test', h boolean default true,
+  i decimal(9, 2) default 1111.11) partition by hash (a)
   partitions 3 stored as kudu
 ---- RESULTS
 ====
@@ -329,62 +332,62 @@ insert into tbl_with_defaults (a, f) values (1, 1), (2, 2), (3, 3), (4, 4)
 NumModifiedRows: 4
 NumRowErrors: 0
 ---- LABELS
-A, B, C, D, E, F, G, H
+A, B, C, D, E, F, G, H, I
 ---- DML_RESULTS: tbl_with_defaults
-1,10,100,1000,NULL,1,'test',true
-2,10,100,1000,NULL,2,'test',true
-3,10,100,1000,NULL,3,'test',true
-4,10,100,1000,NULL,4,'test',true
+1,10,100,1000,NULL,1,'test',true,1111.11
+2,10,100,1000,NULL,2,'test',true,1111.11
+3,10,100,1000,NULL,3,'test',true,1111.11
+4,10,100,1000,NULL,4,'test',true,1111.11
 ---- TYPES
-INT,INT,INT,INT,INT,INT,STRING,BOOLEAN
+INT,INT,INT,INT,INT,INT,STRING,BOOLEAN,DECIMAL
 ====
 ---- QUERY
-insert into tbl_with_defaults values (5, 5, 5, 5, 5, 5, 'row', false)
+insert into tbl_with_defaults values (5, 5, 5, 5, 5, 5, 'row', false, 55555.55)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-A, B, C, D, E, F, G, H
+A, B, C, D, E, F, G, H, I
 ---- DML_RESULTS: tbl_with_defaults
-1,10,100,1000,NULL,1,'test',true
-2,10,100,1000,NULL,2,'test',true
-3,10,100,1000,NULL,3,'test',true
-4,10,100,1000,NULL,4,'test',true
-5,5,5,5,5,5,'row',false
+1,10,100,1000,NULL,1,'test',true,1111.11
+2,10,100,1000,NULL,2,'test',true,1111.11
+3,10,100,1000,NULL,3,'test',true,1111.11
+4,10,100,1000,NULL,4,'test',true,1111.11
+5,5,5,5,5,5,'row',false,55555.55
 ---- TYPES
-INT,INT,INT,INT,INT,INT,STRING,BOOLEAN
+INT,INT,INT,INT,INT,INT,STRING,BOOLEAN,DECIMAL
 ====
 ---- QUERY
-alter table tbl_with_defaults add columns (i int null, j int not null default 10000)
+alter table tbl_with_defaults add columns (j int null, k int not null default 10000)
 ---- RESULTS
 ====
 ---- QUERY
 select * from tbl_with_defaults
 ---- RESULTS
-1,10,100,1000,NULL,1,'test',true,NULL,10000
-2,10,100,1000,NULL,2,'test',true,NULL,10000
-3,10,100,1000,NULL,3,'test',true,NULL,10000
-4,10,100,1000,NULL,4,'test',true,NULL,10000
-5,5,5,5,5,5,'row',false,NULL,10000
+1,10,100,1000,NULL,1,'test',true,1111.11,NULL,10000
+2,10,100,1000,NULL,2,'test',true,1111.11,NULL,10000
+3,10,100,1000,NULL,3,'test',true,1111.11,NULL,10000
+4,10,100,1000,NULL,4,'test',true,1111.11,NULL,10000
+5,5,5,5,5,5,'row',false,55555.55,NULL,10000
 ---- TYPES
-INT,INT,INT,INT,INT,INT,STRING,BOOLEAN,INT,INT
+INT,INT,INT,INT,INT,INT,STRING,BOOLEAN,DECIMAL,INT,INT
 ====
 ---- QUERY
-insert into tbl_with_defaults values (6,6,6,6,6,6,'another row',false,6,6)
+insert into tbl_with_defaults values (6,6,6,6,6,6,'another row',false,66666.66,6,6)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-A, B, C, D, E, F, G, H, I, J
+A, B, C, D, E, F, G, H, I, J, K
 ---- DML_RESULTS: tbl_with_defaults
-1,10,100,1000,NULL,1,'test',true,NULL,10000
-2,10,100,1000,NULL,2,'test',true,NULL,10000
-3,10,100,1000,NULL,3,'test',true,NULL,10000
-4,10,100,1000,NULL,4,'test',true,NULL,10000
-5,5,5,5,5,5,'row',false,NULL,10000
-6,6,6,6,6,6,'another row',false,6,6
+1,10,100,1000,NULL,1,'test',true,1111.11,NULL,10000
+2,10,100,1000,NULL,2,'test',true,1111.11,NULL,10000
+3,10,100,1000,NULL,3,'test',true,1111.11,NULL,10000
+4,10,100,1000,NULL,4,'test',true,1111.11,NULL,10000
+5,5,5,5,5,5,'row',false,55555.55,NULL,10000
+6,6,6,6,6,6,'another row',false,66666.66,6,6
 ---- TYPES
-INT,INT,INT,INT,INT,INT,STRING,BOOLEAN,INT,INT
+INT,INT,INT,INT,INT,INT,STRING,BOOLEAN,DECIMAL,INT,INT
 ====
 ---- QUERY
 # IMPALA-5217: Try to insert NULL to a 'NOT NULL' col with a target col list that leaves
@@ -402,17 +405,17 @@ insert into tbl_with_defaults (a, b, d, f) values (0, 0, null, 0)
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-A, B, C, D, E, F, G, H, I, J
+A, B, C, D, E, F, G, H, I, J, K
 ---- DML_RESULTS: tbl_with_defaults
-0,0,100,NULL,NULL,0,'test',true,NULL,10000
-1,10,100,1000,NULL,1,'test',true,NULL,10000
-2,10,100,1000,NULL,2,'test',true,NULL,10000
-3,10,100,1000,NULL,3,'test',true,NULL,10000
-4,10,100,1000,NULL,4,'test',true,NULL,10000
-5,5,5,5,5,5,'row',false,NULL,10000
-6,6,6,6,6,6,'another row',false,6,6
+0,0,100,NULL,NULL,0,'test',true,1111.11,NULL,10000
+1,10,100,1000,NULL,1,'test',true,1111.11,NULL,10000
+2,10,100,1000,NULL,2,'test',true,1111.11,NULL,10000
+3,10,100,1000,NULL,3,'test',true,1111.11,NULL,10000
+4,10,100,1000,NULL,4,'test',true,1111.11,NULL,10000
+5,5,5,5,5,5,'row',false,55555.55,NULL,10000
+6,6,6,6,6,6,'another row',false,66666.66,6,6
 ---- TYPES
-INT,INT,INT,INT,INT,INT,STRING,BOOLEAN,INT,INT
+INT,INT,INT,INT,INT,INT,STRING,BOOLEAN,DECIMAL,INT,INT
 ====
 ---- QUERY
 create table multiple_partition_cols (x bigint, y bigint, z string, primary key(x, y))


[2/3] impala git commit: IMPALA-5752: Add support for DECIMAL on Kudu tables

Posted by ta...@apache.org.
http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/testdata/workloads/functional-query/queries/QueryTest/kudu_update.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-query/queries/QueryTest/kudu_update.test b/testdata/workloads/functional-query/queries/QueryTest/kudu_update.test
index 8d0d149..8520677 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/kudu_update.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/kudu_update.test
@@ -3,18 +3,19 @@
 create table tdata
   (id int primary key, name string null, valf float null, vali bigint null,
    valv string null, valb boolean null, valt tinyint null, vals smallint null,
-   vald double null)
+   vald double null, valdec4 decimal(9,9) null, valdec8 decimal(18,2) null,
+   valdec16 decimal(38, 0) null)
   PARTITION BY RANGE (PARTITION VALUES < 10, PARTITION 10 <= VALUES < 30,
   PARTITION 30 <= VALUES <= 10000) STORED AS KUDU
 ---- RESULTS
 ====
 ---- QUERY
 insert into tdata values
-(1, "martin", 1.0, 232232323, cast('a' as string), true, 1, 2, 3),
-(2, "david", cast(1.0 as float), 99398493939, cast('b' as string), false, 4, 5, 6),
-(3, "todd", cast(1.0 as float), 993393939, "c", true, 7, 8, 9),
-(40, "he", cast(0.0 as float), 43, cast('e' as string), false, 50, 60, 70),
-(120, "she", cast(0.0 as float), 99, cast('f' as string), true, -1, 0, 1)
+(1, "martin", 1.0, 232232323, cast('a' as string), true, 1, 2, 3, 0.000000001, 2.22, 3),
+(2, "david", cast(1.0 as float), 99398493939, cast('b' as string), false, 4, 5, 6, 0.000000004, 5.55, 6),
+(3, "todd", cast(1.0 as float), 993393939, "c", true, 7, 8, 9, 0.000000007, 8.88, 9),
+(40, "he", cast(0.0 as float), 43, cast('e' as string), false, 50, 60, 70, 0.000000050, 66.60, 70),
+(120, "she", cast(0.0 as float), 99, cast('f' as string), true, -1, 0, 1, -0.000000001, 0.00, 1)
 ---- RESULTS
 : 5
 ---- RUNTIME_PROFILE
@@ -30,15 +31,15 @@ update tdata set vali=43 where id = 1
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'martin',1.0,43,'a',true,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',1.0,993393939,'c',true,7,8,9
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,99,'f',true,-1,0,1
+1,'martin',1.0,43,'a',true,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,99,'f',true,-1,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, equality on key, string
@@ -49,15 +50,15 @@ update tdata set valv=cast('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as varchar(20)) wh
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',true,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',1.0,993393939,'c',true,7,8,9
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,99,'f',true,-1,0,1
+1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',true,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,99,'f',true,-1,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, equality on key, boolean
@@ -66,15 +67,15 @@ update tdata set valb=false where id = 1
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',1.0,993393939,'c',true,7,8,9
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,99,'f',true,-1,0,1
+1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,99,'f',true,-1,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, equality on key, set to NULL
@@ -83,15 +84,15 @@ update tdata set name=null where id = 40
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',1.0,993393939,'c',true,7,8,9
-40,'NULL',0.0,43,'e',false,50,60,70
-120,'she',0.0,99,'f',true,-1,0,1
+1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'NULL',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,99,'f',true,-1,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, equlity on key, set from NULL
@@ -100,15 +101,15 @@ update tdata set name='he' where id = 40
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',1.0,993393939,'c',true,7,8,9
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,99,'f',true,-1,0,1
+1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,99,'f',true,-1,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, equality on key, boundary value
@@ -117,15 +118,15 @@ update tdata set vali = max_bigint() where id = 120
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',1.0,993393939,'c',true,7,8,9
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',true,-1,0,1
+1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',true,-1,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, inequality on key, float
@@ -134,15 +135,15 @@ update tdata set valf = -1 where id > 2 and id < 4
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',-1.0,993393939,'c',true,7,8,9
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',true,-1,0,1
+1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',true,-1,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, inequality on key, tinyint
@@ -151,15 +152,15 @@ update tdata set valt = 10 where id > 100
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',-1.0,993393939,'c',true,7,8,9
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',true,10,0,1
+1,'martin',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',true,10,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, equality on non-key, string
@@ -168,15 +169,15 @@ update tdata set name='unknown' where name = 'martin'
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',-1.0,993393939,'c',true,7,8,9
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',true,10,0,1
+1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,993393939,'c',true,7,8,9,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',true,10,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # single row, inequality on non-key, double
@@ -185,15 +186,32 @@ update tdata set vald = 0 where valf < 0
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,99398493939,'b',false,4,5,6
-3,'todd',-1.0,993393939,'c',true,7,8,0
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',true,10,0,1
+1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,993393939,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',true,10,0,1,-0.000000001,0.00,1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
+====
+---- QUERY
+# single row, inequality on non-key, decimal
+update tdata set valdec4 = 0.000000001, valdec16 = -1 where valdec4 < 0
+---- RUNTIME_PROFILE
+NumModifiedRows: 1
+NumRowErrors: 0
+---- LABELS
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
+---- DML_RESULTS: tdata
+1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,99398493939,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,993393939,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',true,10,0,1,0.000000001,0.00,-1
+---- TYPES
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # multiple rows, predicate on key
@@ -202,15 +220,15 @@ update tdata set vali=43 where id > 1 and id < 10
 NumModifiedRows: 2
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,43,'b',false,4,5,6
-3,'todd',-1.0,43,'c',true,7,8,0
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',true,10,0,1
+1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,43,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,43,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',true,10,0,1,0.000000001,0.00,-1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # multiple rows, predicate on non-key
@@ -219,15 +237,15 @@ update tdata set valb=false where name LIKE '%he'
 NumModifiedRows: 2
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,43,'b',false,4,5,6
-3,'todd',-1.0,43,'c',true,7,8,0
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',false,10,0,1
+1,'unknown',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,43,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,43,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',false,10,0,1,0.000000001,0.00,-1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # update the same row multiple times: cross join produces 5 identical updates
@@ -236,15 +254,15 @@ update a set a.name='they' from tdata a, tdata b where a.id = 1
 NumModifiedRows: 5
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'they',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,43,'b',false,4,5,6
-3,'todd',-1.0,43,'c',true,7,8,0
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',false,10,0,1
+1,'they',1.0,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,43,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,43,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',false,10,0,1,0.000000001,0.00,-1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # value of update is a constant expression
@@ -253,15 +271,15 @@ update tdata set valf = 1 + 2 where id = 1
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'they',3,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,43,'b',false,4,5,6
-3,'todd',-1.0,43,'c',true,7,8,0
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',false,10,0,1
+1,'they',3,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,43,'b',false,4,5,6,0.000000004,5.55,6
+3,'todd',-1.0,43,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',false,10,0,1,0.000000001,0.00,-1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # value of update is a non-constant expression
@@ -270,15 +288,15 @@ update tdata set name = concat(name, name) where id % 2 = 1
 NumModifiedRows: 2
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'theythey',3,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,43,'b',false,4,5,6
-3,'toddtodd',-1.0,43,'c',true,7,8,0
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',false,10,0,1
+1,'theythey',3,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,43,'b',false,4,5,6,0.000000004,5.55,6
+3,'toddtodd',-1.0,43,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',false,10,0,1,0.000000001,0.00,-1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # error - update key column
@@ -293,15 +311,15 @@ update tdata set name = 'none' where id = 10
 NumModifiedRows: 0
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'theythey',3,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,43,'b',false,4,5,6
-3,'toddtodd',-1.0,43,'c',true,7,8,0
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',false,10,0,1
+1,'theythey',3,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,43,'b',false,4,5,6,0.000000004,5.55,6
+3,'toddtodd',-1.0,43,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',false,10,0,1,0.000000001,0.00,-1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 # Try to update a row with a primary key value that is not covered by the existing range
@@ -311,20 +329,20 @@ update tdata set vali = 10 where id = 10001
 NumModifiedRows: 0
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC4, VALDEC8, VALDEC16
 ---- DML_RESULTS: tdata
-1,'theythey',3,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3
-2,'david',1.0,43,'b',false,4,5,6
-3,'toddtodd',-1.0,43,'c',true,7,8,0
-40,'he',0.0,43,'e',false,50,60,70
-120,'she',0.0,9223372036854775807,'f',false,10,0,1
+1,'theythey',3,43,'aaaaaaaaaaaaaaaaaaaa',false,1,2,3,0.000000001,2.22,3
+2,'david',1.0,43,'b',false,4,5,6,0.000000004,5.55,6
+3,'toddtodd',-1.0,43,'c',true,7,8,0,0.000000007,8.88,9
+40,'he',0.0,43,'e',false,50,60,70,0.000000050,66.60,70
+120,'she',0.0,9223372036854775807,'f',false,10,0,1,0.000000001,0.00,-1
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL,DECIMAL,DECIMAL
 ====
 ---- QUERY
 insert into tdata
 select id, string_col, float_col, bigint_col, string_col, bool_col, tinyint_col,
-smallint_col, double_col from functional_kudu.alltypes
+smallint_col, double_col, NULL, NULL, NULL from functional_kudu.alltypes
 ---- RESULTS
 : 7295
 ---- RUNTIME_PROFILE

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/testdata/workloads/functional-query/queries/QueryTest/kudu_upsert.test
----------------------------------------------------------------------
diff --git a/testdata/workloads/functional-query/queries/QueryTest/kudu_upsert.test b/testdata/workloads/functional-query/queries/QueryTest/kudu_upsert.test
index 57aaa46..1c12f33 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/kudu_upsert.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/kudu_upsert.test
@@ -3,149 +3,149 @@
 create table tdata
   (id int primary key, name string null, valf float null, vali bigint null,
    valv string null, valb boolean null, valt tinyint null, vals smallint null,
-   vald double null)
+   vald double null, valdec decimal(9, 0) null)
   PARTITION BY RANGE (PARTITION VALUES < 10, PARTITION 10 <= VALUES < 30,
   PARTITION 30 <= VALUES) STORED AS KUDU
 ---- RESULTS
 ====
 ---- QUERY
 insert into table tdata values
-(40,'he',0,43,'e',false,35,36,1.2),
-(1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0),
-(2,'david',1,43,'b',false,0,0,0),
-(3,'todd',1,43,'c',true,3,3,3)
+(40,'he',0,43,'e',false,35,36,1.2,37),
+(1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3),
+(2,'david',1,43,'b',false,0,0,0,0),
+(3,'todd',1,43,'c',true,3,3,3,3)
 ---- RESULTS
 : 4
 ====
 ---- QUERY
 # VALUES, single row, all cols, results in insert
-upsert into table tdata values (4, 'a', 0, 1, 'b', false, 1, 2, 1.5)
+upsert into table tdata values (4, 'a', 0, 1, 'b', false, 1, 2, 1.5, 4)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'a',0,1,'b',false,1,2,1.5
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'a',0,1,'b',false,1,2,1.5,4
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all cols, results in update
-upsert into table tdata values (4, 'b', -1, 1, 'a', true, 2, 3, 2.5)
+upsert into table tdata values (4, 'b', -1, 1, 'a', true, 2, 3, 2.5, 5)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'b',-1,1,'a',true,2,3,2.5
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'b',-1,1,'a',true,2,3,2.5,5
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all cols, insert NULL all types
-upsert into table tdata values (10, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
+upsert into table tdata values (10, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'b',-1,1,'a',true,2,3,2.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'b',-1,1,'a',true,2,3,2.5,5
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all cols, update NULL all types
-upsert into table tdata values (4, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
+upsert into table tdata values (4, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all cols, update from NULL all types
-upsert into table tdata values (4, 'four', 5, 6, 'f', true, 7, 8, 7.5)
+upsert into table tdata values (4, 'four', 5, 6, 'f', true, 7, 8, 7.5, 9)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'four',5,6,'f',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'four',5,6,'f',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all cols, insert boundary values
 upsert into table tdata values
 (max_int(), '', cast('nan' as float), min_bigint(), '', true, max_tinyint(),
-  min_smallint(), cast('inf' as double))
+  min_smallint(), cast('inf' as double), cast(999999999 as decimal(9, 0)))
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'four',5,6,'f',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',NaN,-9223372036854775808,'',true,127,-32768,Infinity
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'four',5,6,'f',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',NaN,-9223372036854775808,'',true,127,-32768,Infinity,999999999
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all cols, update boundary values
 upsert into table tdata values
 (max_int(), '', cast('-inf' as float), max_bigint(), '', true, min_tinyint(),
-  max_smallint(), cast('nan' as double))
+  max_smallint(), cast('nan' as double), cast(-999999999 as decimal(9, 0)))
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'four',5,6,'f',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'four',5,6,'f',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, subset of cols, results in insert
@@ -154,18 +154,18 @@ upsert into table tdata (id, name, vali, valb, vald) values (5, 'five', -5, NULL
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'four',5,6,'f',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
-5,'five',NULL,-5,'NULL',NULL,NULL,NULL,0.5
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'four',5,6,'f',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'five',NULL,-5,'NULL',NULL,NULL,NULL,0.5,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, subset of cols, results in update
@@ -174,44 +174,44 @@ upsert into table tdata (id, name, valf, valv, valb) values (5, NULL, 0, 'six',
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0
-2,'david',1,43,'b',false,0,0,0
-3,'todd',1,43,'c',true,3,3,3
-4,'four',5,6,'f',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
-5,'NULL',0,-5,'six',false,NULL,NULL,0.5
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'unknown',1,43,'aaaaaaaaaaaaaaaaaaaa',false,-1,-2,0,-3
+2,'david',1,43,'b',false,0,0,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'four',5,6,'f',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'NULL',0,-5,'six',false,NULL,NULL,0.5,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, multiple rows, all cols, no errors
 upsert into table tdata values
-(1, 'one', NULL, 44, 'a', true, -1, -2, 0),
-(6, '', -6, 40, 'b', NULL, 0, 0, 10),
-(7, 'seven', 0, min_bigint(), NULL, true, 7, 1, 2),
-(2, 'you', cast('inf' as float), 0, 't', false, NULL, min_smallint(), 0)
+(1, 'one', NULL, 44, 'a', true, -1, -2, 0, 0),
+(6, '', -6, 40, 'b', NULL, 0, 0, 10, 11),
+(7, 'seven', 0, min_bigint(), NULL, true, 7, 1, 2, 3),
+(2, 'you', cast('inf' as float), 0, 't', false, NULL, min_smallint(), 0, 0)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 4
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'one',NULL,44,'a',true,-1,-2,0
-2,'you',Infinity,0,'t',false,NULL,-32768,0
-3,'todd',1,43,'c',true,3,3,3
-4,'four',5,6,'f',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
-5,'NULL',0,-5,'six',false,NULL,NULL,0.5
-6,'',-6,40,'b',NULL,0,0,10
-7,'seven',0,-9223372036854775808,'NULL',true,7,1,2
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'one',NULL,44,'a',true,-1,-2,0,0
+2,'you',Infinity,0,'t',false,NULL,-32768,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'four',5,6,'f',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'NULL',0,-5,'six',false,NULL,NULL,0.5,NULL
+6,'',-6,40,'b',NULL,0,0,10,11
+7,'seven',0,-9223372036854775808,'NULL',true,7,1,2,3
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, multiple rows, subset of cols, no errors
@@ -224,72 +224,72 @@ upsert into table tdata (id, valb, name, vali) values
 NumModifiedRows: 4
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'NULL',NULL,1,'a',true,-1,-2,0
-2,'you',Infinity,0,'t',false,NULL,-32768,0
-3,'todd',1,43,'c',true,3,3,3
-4,'four',5,6,'f',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
-5,'five',0,10,'six',NULL,NULL,NULL,0.5
-6,'',-6,40,'b',NULL,0,0,10
-7,'seven',0,-9223372036854775808,'NULL',true,7,1,2
-8,'hello',NULL,2,'NULL',false,NULL,NULL,NULL
-9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'NULL',NULL,1,'a',true,-1,-2,0,0
+2,'you',Infinity,0,'t',false,NULL,-32768,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'four',5,6,'f',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'five',0,10,'six',NULL,NULL,NULL,0.5,NULL
+6,'',-6,40,'b',NULL,0,0,10,11
+7,'seven',0,-9223372036854775808,'NULL',true,7,1,2,3
+8,'hello',NULL,2,'NULL',false,NULL,NULL,NULL,NULL
+9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # SELECT, all cols, single row, no errors
 upsert into table tdata
-select id, 'a', valf, vali, valv, NULL, valt, vals, 3 from tdata where id = 1
+select id, 'a', valf, vali, valv, NULL, valt, vals, 3, valdec from tdata where id = 1
 ---- RUNTIME_PROFILE
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'he',0,43,'e',false,35,36,1.2
-1,'a',NULL,1,'a',NULL,-1,-2,3
-2,'you',Infinity,0,'t',false,NULL,-32768,0
-3,'todd',1,43,'c',true,3,3,3
-4,'four',5,6,'f',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
-5,'five',0,10,'six',NULL,NULL,NULL,0.5
-6,'',-6,40,'b',NULL,0,0,10
-7,'seven',0,-9223372036854775808,'NULL',true,7,1,2
-8,'hello',NULL,2,'NULL',false,NULL,NULL,NULL
-9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL
+40,'he',0,43,'e',false,35,36,1.2,37
+1,'a',NULL,1,'a',NULL,-1,-2,3,0
+2,'you',Infinity,0,'t',false,NULL,-32768,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'four',5,6,'f',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'five',0,10,'six',NULL,NULL,NULL,0.5,NULL
+6,'',-6,40,'b',NULL,0,0,10,11
+7,'seven',0,-9223372036854775808,'NULL',true,7,1,2,3
+8,'hello',NULL,2,'NULL',false,NULL,NULL,NULL,NULL
+9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # SELECT, all cols, multiple rows, no errors
 upsert into table tdata
-select id, valv, valf, vali, name, valb, valt, vals, vald from tdata where id % 2 = 0
+select id, valv, valf, vali, name, valb, valt, vals, vald, valdec from tdata where id % 2 = 0
 ---- RUNTIME_PROFILE
 NumModifiedRows: 6
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'e',0,43,'he',false,35,36,1.2
-1,'a',NULL,1,'a',NULL,-1,-2,3
-2,'t',Infinity,0,'you',false,NULL,-32768,0
-3,'todd',1,43,'c',true,3,3,3
-4,'f',5,6,'four',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
-5,'five',0,10,'six',NULL,NULL,NULL,0.5
-6,'b',-6,40,'',NULL,0,0,10
-7,'seven',0,-9223372036854775808,'NULL',true,7,1,2
-8,'NULL',NULL,2,'hello',false,NULL,NULL,NULL
-9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL
+40,'e',0,43,'he',false,35,36,1.2,37
+1,'a',NULL,1,'a',NULL,-1,-2,3,0
+2,'t',Infinity,0,'you',false,NULL,-32768,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'f',5,6,'four',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'five',0,10,'six',NULL,NULL,NULL,0.5,NULL
+6,'b',-6,40,'',NULL,0,0,10,11
+7,'seven',0,-9223372036854775808,'NULL',true,7,1,2,3
+8,'NULL',NULL,2,'hello',false,NULL,NULL,NULL,NULL
+9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # SELECT, subset of cols, single row, no errors
@@ -299,23 +299,23 @@ select int_col, string_col, bigint_col from functional.alltypes where id = 0
 NumModifiedRows: 1
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'e',0,43,'he',false,35,36,1.2
-1,'a',NULL,1,'a',NULL,-1,-2,3
-2,'t',Infinity,0,'you',false,NULL,-32768,0
-3,'todd',1,43,'c',true,3,3,3
-4,'f',5,6,'four',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
-5,'five',0,10,'six',NULL,NULL,NULL,0.5
-6,'b',-6,40,'',NULL,0,0,10
-7,'seven',0,-9223372036854775808,'NULL',true,7,1,2
-8,'NULL',NULL,2,'hello',false,NULL,NULL,NULL
-9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL
-0,'NULL',NULL,0,'0',NULL,NULL,NULL,NULL
+40,'e',0,43,'he',false,35,36,1.2,37
+1,'a',NULL,1,'a',NULL,-1,-2,3,0
+2,'t',Infinity,0,'you',false,NULL,-32768,0,0
+3,'todd',1,43,'c',true,3,3,3,3
+4,'f',5,6,'four',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'five',0,10,'six',NULL,NULL,NULL,0.5,NULL
+6,'b',-6,40,'',NULL,0,0,10,11
+7,'seven',0,-9223372036854775808,'NULL',true,7,1,2,3
+8,'NULL',NULL,2,'hello',false,NULL,NULL,NULL,NULL
+9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL,NULL
+0,'NULL',NULL,0,'0',NULL,NULL,NULL,NULL,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # SELECT, subset of cols, multiple rows, no errors
@@ -325,27 +325,53 @@ select int_col, bool_col, string_col, tinyint_col from functional.alltypes where
 NumModifiedRows: 4
 NumRowErrors: 0
 ---- LABELS
-ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
 ---- DML_RESULTS: tdata
-40,'e',0,43,'he',false,35,36,1.2
-1,'1',NULL,1,'a',false,1,-2,3
-2,'2',Infinity,0,'you',true,2,-32768,0
-3,'3',1,43,'c',false,3,3,3
-4,'f',5,6,'four',true,7,8,7.5
-10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL
-2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN
-5,'five',0,10,'six',NULL,NULL,NULL,0.5
-6,'b',-6,40,'',NULL,0,0,10
-7,'seven',0,-9223372036854775808,'NULL',true,7,1,2
-8,'NULL',NULL,2,'hello',false,NULL,NULL,NULL
-9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL
-0,'0',NULL,0,'0',true,0,NULL,NULL
+40,'e',0,43,'he',false,35,36,1.2,37
+1,'1',NULL,1,'a',false,1,-2,3,0
+2,'2',Infinity,0,'you',true,2,-32768,0,0
+3,'3',1,43,'c',false,3,3,3,3
+4,'f',5,6,'four',true,7,8,7.5,9
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'five',0,10,'six',NULL,NULL,NULL,0.5,NULL
+6,'b',-6,40,'',NULL,0,0,10,11
+7,'seven',0,-9223372036854775808,'NULL',true,7,1,2,3
+8,'NULL',NULL,2,'hello',false,NULL,NULL,NULL,NULL
+9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL,NULL
+0,'0',NULL,0,'0',true,0,NULL,NULL,NULL
 ---- TYPES
-INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
+====
+---- QUERY
+# SELECT, decimal column, multiple rows, no errors
+upsert into table tdata (id, valdec)
+select id, cast((valdec * 2) as decimal(9,0)) from tdata where valdec > 0
+---- RUNTIME_PROFILE
+NumModifiedRows: 5
+NumRowErrors: 0
+---- LABELS
+ID, NAME, VALF, VALI, VALV, VALB, VALT, VALS, VALD, VALDEC
+---- DML_RESULTS: tdata
+40,'e',0,43,'he',false,35,36,1.2,74
+1,'1',NULL,1,'a',false,1,-2,3,0
+2,'2',Infinity,0,'you',true,2,-32768,0,0
+3,'3',1,43,'c',false,3,3,3,6
+4,'f',5,6,'four',true,7,8,7.5,18
+10,'NULL',NULL,NULL,'NULL',NULL,NULL,NULL,NULL,NULL
+2147483647,'',-Infinity,9223372036854775807,'',true,-128,32767,NaN,-999999999
+5,'five',0,10,'six',NULL,NULL,NULL,0.5,NULL
+6,'b',-6,40,'',NULL,0,0,10,22
+7,'seven',0,-9223372036854775808,'NULL',true,7,1,2,6
+8,'NULL',NULL,2,'hello',false,NULL,NULL,NULL,NULL
+9,'nine',NULL,9,'NULL',true,NULL,NULL,NULL,NULL
+0,'0',NULL,0,'0',true,0,NULL,NULL,NULL
+---- TYPES
+INT,STRING,FLOAT,BIGINT,STRING,BOOLEAN,TINYINT,SMALLINT,DOUBLE,DECIMAL
 ====
 ---- QUERY
 # VALUES, single row, all cols, null for non-nullable column
-upsert into table tdata values (null, '', 0, 0, cast('' as VARCHAR(20)), false, 0, 0, 0)
+upsert into table tdata values (null, '', 0, 0, cast('' as VARCHAR(20)), false, 0, 0, 0, null)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 0
 NumRowErrors: 1
@@ -360,10 +386,10 @@ NumRowErrors: 1
 ---- QUERY
 # VALUES, multiple rows, all cols, null for non-nullable column
 upsert into table tdata values
-(3,'todd',1,43,'c',true,3,3,3),
-(4,'four',5,6,'f',true,7,8,7.5),
-(6,'',-6,40,'b',NULL,0,0,10),
-(NULL,'seven',0,0,'NULL',true,7,1,2)
+(3,'todd',1,43,'c',true,3,3,3,null),
+(4,'four',5,6,'f',true,7,8,7.5,null),
+(6,'',-6,40,'b',NULL,0,0,10,null),
+(NULL,'seven',0,0,'NULL',true,7,1,2,null)
 ---- RUNTIME_PROFILE
 NumModifiedRows: 3
 NumRowErrors: 1

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/tests/query_test/test_decimal_queries.py
----------------------------------------------------------------------
diff --git a/tests/query_test/test_decimal_queries.py b/tests/query_test/test_decimal_queries.py
index a250ae2..3a14ed3 100644
--- a/tests/query_test/test_decimal_queries.py
+++ b/tests/query_test/test_decimal_queries.py
@@ -43,7 +43,7 @@ class TestDecimalQueries(ImpalaTestSuite):
     cls.ImpalaTestMatrix.add_constraint(lambda v:\
         (v.get_value('table_format').file_format == 'text' and
          v.get_value('table_format').compression_codec == 'none') or
-         v.get_value('table_format').file_format == 'parquet')
+         v.get_value('table_format').file_format in ['parquet', 'kudu'])
 
   def test_queries(self, vector):
     self.run_test_case('QueryTest/decimal', vector)
@@ -60,7 +60,7 @@ class TestDecimalExprs(ImpalaTestSuite):
   def add_test_dimensions(cls):
     super(TestDecimalExprs, cls).add_test_dimensions()
     cls.ImpalaTestMatrix.add_constraint(lambda v:
-        (v.get_value('table_format').file_format == 'parquet'))
+        (v.get_value('table_format').file_format in ['parquet', 'kudu']))
 
   def test_exprs(self, vector):
     self.run_test_case('QueryTest/decimal-exprs', vector)

http://git-wip-us.apache.org/repos/asf/impala/blob/0c8eba07/tests/query_test/test_kudu.py
----------------------------------------------------------------------
diff --git a/tests/query_test/test_kudu.py b/tests/query_test/test_kudu.py
index ddf59f2..3d7b727 100644
--- a/tests/query_test/test_kudu.py
+++ b/tests/query_test/test_kudu.py
@@ -357,7 +357,7 @@ class TestKuduOperations(KuduTestSuite):
       pytest.skip("Only runs in exhaustive to reduce core time.")
     table_name = "%s.storage_attrs" % unique_database
     types = ['boolean', 'tinyint', 'smallint', 'int', 'bigint', 'float', 'double', \
-        'string', 'timestamp']
+        'string', 'timestamp', 'decimal(9, 2)', 'decimal(18)', 'decimal(38, 38)']
 
     create_query = "create table %s (id int primary key" % table_name
     for t in types:
@@ -485,6 +485,7 @@ class TestCreateExternalTable(KuduTestSuite):
 
   def test_col_types(self, cursor, kudu_client):
     """Check that a table can be created using all available column types."""
+    # TODO: Add DECIMAL when the Kudu python client supports decimal
     kudu_types = [STRING, BOOL, DOUBLE, FLOAT, INT16, INT32, INT64, INT8]
     with self.temp_kudu_table(kudu_client, kudu_types) as kudu_table:
       impala_table_name = self.get_kudu_table_base_name(kudu_table.name)