[ 
https://issues.apache.org/jira/browse/CALCITE-980?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15025458#comment-15025458
 ] 

Vladimir Sitnikov edited comment on CALCITE-980 at 11/24/15 9:33 PM:
---------------------------------------------------------------------

The problem is with OR implementor in nullsAs=TRUE mode: 
https://github.com/apache/calcite/blob/d012b245e4e040ae94bb3d7045cf4d71af8ac279/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java#L476-L488

The following monkey-patch solves the particular NPE. However, I would like 
OR/AND implementors to be reviewed & simplified.

{noformat}
iff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 07f3f43..fb4dda6 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -473,7 +473,7 @@ public Expression implement(
           if (!nullable(call2, 0) && !nullable(call2, 1)) {
             return Expressions.orElse(t0, t1);
           }
-          return optimize(
+          return optimize(nullAs.handle(
               Expressions.condition(
                   Expressions.equal(t0, NULL_EXPR),
                   Expressions.condition(
@@ -485,7 +485,7 @@ public Expression implement(
                   Expressions.condition(
                       Expressions.not(t0),
                       t1,
-                      BOXED_TRUE_EXPR)));
+                      BOXED_TRUE_EXPR))));
         }
       };
     case NOT:
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java 
b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 3709eba..c1b4290 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -4277,6 +4277,16 @@ private void startOfGroupStep3(String startOfGroup) {
             "empid=100; deptno=10; name=Bill; salary=10000.0; 
commission=1000\n");
   }

+  /** Tests CALCITE-980: Not (C='a' or C='b') causes NPE */
+  @Test public void testWhereNotOrNullable() {
+    CalciteAssert.that()
+        .with(CalciteAssert.Config.REGULAR)
+        .query("with tst(c) as (values('a'),('b'),('c'),(cast(null as 
varchar)))"
+                + " select * from tst where not (c='a' or c='b')")
+        .returns(
+            "qwert\n");
+  }
+
   /** Tests the LIKE operator. */
   @Test public void testLike() {
     CalciteAssert.that(){noformat}


was (Author: vladimirsitnikov):
The problem is with OR implementor in nullsAs=TRUE mode: 
https://github.com/apache/calcite/blob/d012b245e4e040ae94bb3d7045cf4d71af8ac279/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java#L476-L488

The following monkey-patch solves a particular NPE. However, I would like 
OR/AND implementors to be reviewed & simplified.

{noformat}
iff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 07f3f43..fb4dda6 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -473,7 +473,7 @@ public Expression implement(
           if (!nullable(call2, 0) && !nullable(call2, 1)) {
             return Expressions.orElse(t0, t1);
           }
-          return optimize(
+          return optimize(nullAs.handle(
               Expressions.condition(
                   Expressions.equal(t0, NULL_EXPR),
                   Expressions.condition(
@@ -485,7 +485,7 @@ public Expression implement(
                   Expressions.condition(
                       Expressions.not(t0),
                       t1,
-                      BOXED_TRUE_EXPR)));
+                      BOXED_TRUE_EXPR))));
         }
       };
     case NOT:
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java 
b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 3709eba..c1b4290 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -4277,6 +4277,16 @@ private void startOfGroupStep3(String startOfGroup) {
             "empid=100; deptno=10; name=Bill; salary=10000.0; 
commission=1000\n");
   }

+  /** Tests CALCITE-980: Not (C='a' or C='b') causes NPE */
+  @Test public void testWhereNotOrNullable() {
+    CalciteAssert.that()
+        .with(CalciteAssert.Config.REGULAR)
+        .query("with tst(c) as (values('a'),('b'),('c'),(cast(null as 
varchar)))"
+                + " select * from tst where not (c='a' or c='b')")
+        .returns(
+            "qwert\n");
+  }
+
   /** Tests the LIKE operator. */
   @Test public void testLike() {
     CalciteAssert.that(){noformat}

> Not (C='a' or C='b') causes NPE
> -------------------------------
>
>                 Key: CALCITE-980
>                 URL: https://issues.apache.org/jira/browse/CALCITE-980
>             Project: Calcite
>          Issue Type: Bug
>    Affects Versions: 1.4.0-incubating
>            Reporter: liyang
>            Assignee: Julian Hyde
>
> A where clause like Not (C='a' or C='b') causes NPE if C has NULL value.
> The generated code snippet looks like:
> {code}
> /*  65 */           public boolean moveNext() {
> /*  66 */             while (inputEnumerator.moveNext()) {
> /*  67 */               final Object[] current = (Object[]) 
> inputEnumerator.current();
> /*  68 */               final String inp21_ = current[21] == null ? (String) 
> null : current[21].toString();
> /*  69 */               final Boolean v = inp21_ == null ? (Boolean) null : 
> Boolean.valueOf(org.apache.calcite.runtime.SqlFunctions.eq(inp21_, "A"));
> /*  70 */               final Boolean v0 = inp21_ == null ? (Boolean) null : 
> Boolean.valueOf(org.apache.calcite.runtime.SqlFunctions.eq(inp21_, "B"));
> /*  71 */               if (!(v == null ? (v0 == null || !v0 ? (Boolean) null 
> : Boolean.TRUE) : v ? Boolean.TRUE : v0)) {
> /*  72 */                 return true;
> /*  73 */               }
> /*  74 */             }
> /*  75 */             return false;
> /*  76 */           }
> {code}
> And NPE is thrown at line #71 if inp21_ is null.
> Stacktrace:
> {code}
> Caused by: java.lang.NullPointerException
>       at Baz$1$1.moveNext(ANONYMOUS.java:71)
>       at 
> org.apache.calcite.linq4j.EnumerableDefaults.groupBy_(EnumerableDefaults.java:737)
>       at 
> org.apache.calcite.linq4j.EnumerableDefaults.groupBy(EnumerableDefaults.java:677)
>       at 
> org.apache.calcite.linq4j.DefaultEnumerable.groupBy(DefaultEnumerable.java:301)
>       at Baz.bind(Baz.java:95)
>       at 
> org.apache.calcite.jdbc.CalcitePrepare$CalciteSignature.enumerable(CalcitePrepare.java:281)
>       at 
> org.apache.calcite.jdbc.CalciteConnectionImpl.enumerable(CalciteConnectionImpl.java:235)
>       at 
> org.apache.calcite.jdbc.CalciteMetaImpl.createIterable(CalciteMetaImpl.java:533)
>       at 
> org.apache.calcite.avatica.AvaticaResultSet.execute(AvaticaResultSet.java:184)
>       at 
> org.apache.calcite.jdbc.CalciteResultSet.execute(CalciteResultSet.java:63)
>       at 
> org.apache.calcite.jdbc.CalciteResultSet.execute(CalciteResultSet.java:42)
>       at 
> org.apache.calcite.avatica.AvaticaConnection$1.execute(AvaticaConnection.java:473)
>       at 
> org.apache.calcite.jdbc.CalciteMetaImpl.prepareAndExecute(CalciteMetaImpl.java:566)
>       at 
> org.apache.calcite.avatica.AvaticaConnection.prepareAndExecuteInternal(AvaticaConnection.java:477)
>       at 
> org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:109)
>       ... 29 more
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to