You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by am...@apache.org on 2015/02/28 20:23:02 UTC

drill git commit: DRILL-2328: For concat function, null input is treated as empty string; for concat operator (i.e., ||), if any input is null, the output is null

Repository: drill
Updated Branches:
  refs/heads/master 02d23cb8d -> c8a241b06


DRILL-2328: For concat function, null input is treated as empty string; for concat operator (i.e., ||), if any input is null, the output is null


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

Branch: refs/heads/master
Commit: c8a241b064c386fe21d7d7cb987c2b8cfdee43e4
Parents: 02d23cb
Author: Hsuan-Yi Chu <hs...@usc.edu>
Authored: Thu Feb 26 19:51:04 2015 -0800
Committer: Hsuan-Yi Chu <hs...@usc.edu>
Committed: Fri Feb 27 21:54:08 2015 -0800

----------------------------------------------------------------------
 .../common/expression/FunctionCallFactory.java  |  2 +-
 .../exec/expr/fn/impl/StringFunctions.java      | 26 +++++++++-
 .../org/apache/drill/TestExampleQueries.java    | 54 ++++++++++++++++++++
 3 files changed, 80 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/c8a241b0/common/src/main/java/org/apache/drill/common/expression/FunctionCallFactory.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/drill/common/expression/FunctionCallFactory.java b/common/src/main/java/org/apache/drill/common/expression/FunctionCallFactory.java
index 422800b..9128a78 100644
--- a/common/src/main/java/org/apache/drill/common/expression/FunctionCallFactory.java
+++ b/common/src/main/java/org/apache/drill/common/expression/FunctionCallFactory.java
@@ -39,7 +39,7 @@ public class FunctionCallFactory {
     opToFuncTable.put("*", "multiply");
     opToFuncTable.put("%", "modulo");
     opToFuncTable.put("^", "xor");
-    opToFuncTable.put("||", "concat");
+    opToFuncTable.put("||", "concatOperator");
     opToFuncTable.put("or", "booleanOr");
     opToFuncTable.put("and", "booleanAnd");
     opToFuncTable.put(">", "greater_than");

http://git-wip-us.apache.org/repos/asf/drill/blob/c8a241b0/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctions.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctions.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctions.java
index 7ba4a30..a3bc1de 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctions.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctions.java
@@ -837,6 +837,31 @@ public class StringFunctions{
     } // end of eval
   }
 
+  @FunctionTemplate(name = "concatOperator", scope = FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
+  public static class ConcatOperator implements DrillSimpleFunc{
+    @Param  VarCharHolder left;
+    @Param  VarCharHolder right;
+    @Output VarCharHolder out;
+    @Inject DrillBuf buffer;
+
+    public void setup(RecordBatch incoming) {
+    }
+
+    public void eval() {
+      out.buffer = buffer = buffer.reallocIfNeeded( (left.end - left.start) + (right.end - right.start));
+      out.start = out.end = 0;
+
+      int id = 0;
+      for (id = left.start; id < left.end; id++) {
+        out.buffer.setByte(out.end++, left.buffer.getByte(id));
+      }
+
+      for (id = right.start; id < right.end; id++) {
+        out.buffer.setByte(out.end++, right.buffer.getByte(id));
+      }
+    }
+  }
+
   //Concatenate the text representations of the arguments. NULL arguments are ignored.
   //TODO: NullHanding.INTERNAL for DrillSimpleFunc requires change in code generation.
   @FunctionTemplate(name = "concat", scope = FunctionScope.SIMPLE, nulls = NullHandling.INTERNAL)
@@ -864,7 +889,6 @@ public class StringFunctions{
         out.buffer.setByte(out.end++, right.buffer.getByte(id));
       }
     }
-
   }
 
   @FunctionTemplate(name = "concat", scope = FunctionScope.SIMPLE, nulls = NullHandling.INTERNAL)

http://git-wip-us.apache.org/repos/asf/drill/blob/c8a241b0/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java b/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
index c59d0af..225b21e 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
@@ -30,6 +30,60 @@ import org.junit.Test;
 public class TestExampleQueries extends BaseTestQuery{
   static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestExampleQueries.class);
 
+  @Test // see DRILL-2328
+  public void testConcatOnNull() throws Exception {
+    try {
+      test("use dfs.tmp");
+      test("create view concatNull as (select * from cp.`customer.json` where customer_id < 5);");
+
+      // Test Left Null
+      testBuilder()
+          .sqlQuery("select (mi || lname) as CONCATOperator, mi, lname, concat(mi, lname) as CONCAT from concatNull")
+          .ordered()
+          .baselineColumns("CONCATOperator", "mi", "lname","CONCAT")
+          .baselineValues("A.Nowmer", "A.", "Nowmer", "A.Nowmer")
+          .baselineValues("I.Whelply", "I.", "Whelply", "I.Whelply")
+          .baselineValues(null, null, "Derry", "Derry")
+          .baselineValues("J.Spence", "J.", "Spence", "J.Spence")
+          .build().run();
+
+      // Test Right Null
+      testBuilder()
+          .sqlQuery("select (lname || mi) as CONCATOperator, lname, mi, concat(lname, mi) as CONCAT from concatNull")
+          .ordered()
+          .baselineColumns("CONCATOperator", "lname", "mi", "CONCAT")
+          .baselineValues("NowmerA.", "Nowmer", "A.", "NowmerA.")
+          .baselineValues("WhelplyI.", "Whelply", "I.", "WhelplyI.")
+          .baselineValues(null, "Derry", null, "Derry")
+          .baselineValues("SpenceJ.", "Spence", "J.", "SpenceJ.")
+          .build().run();
+
+      // Test Two Sides
+      testBuilder()
+          .sqlQuery("select (mi || mi) as CONCATOperator, mi, mi, concat(mi, mi) as CONCAT from concatNull")
+          .ordered()
+          .baselineColumns("CONCATOperator", "mi", "mi0", "CONCAT")
+          .baselineValues("A.A.", "A.", "A.", "A.A.")
+          .baselineValues("I.I.", "I.", "I.", "I.I.")
+          .baselineValues(null, null, null, "")
+          .baselineValues("J.J.", "J.", "J.", "J.J.")
+          .build().run();
+
+      testBuilder()
+          .sqlQuery("select (cast(null as varchar(10)) || lname) as CONCATOperator, " +
+              "cast(null as varchar(10)) as NullColumn, lname, concat(cast(null as varchar(10)), lname) as CONCAT from concatNull")
+          .ordered()
+          .baselineColumns("CONCATOperator", "NullColumn", "lname", "CONCAT")
+          .baselineValues(null, null, "Nowmer", "Nowmer")
+          .baselineValues(null, null, "Whelply", "Whelply")
+          .baselineValues(null, null, "Derry", "Derry")
+          .baselineValues(null, null, "Spence", "Spence")
+          .build().run();
+    } finally {
+      test("drop view concatNull;");
+    }
+  }
+
   @Test // see DRILL-2054
   public void testConcatOperator() throws Exception {
     testBuilder()