This is an automated email from the ASF dual-hosted git repository.
mbudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new 6b577851fb [CALCITE-6422] Query with '<>' throws NullPointerException
during materialized view matching
6b577851fb is described below
commit 6b577851fbdc4cb87aca2c939cf74bfd9d5f3eb8
Author: Mou Wu <[email protected]>
AuthorDate: Mon May 27 16:52:05 2024 +0800
[CALCITE-6422] Query with '<>' throws NullPointerException during
materialized view matching
---
.../apache/calcite/plan/SubstitutionVisitor.java | 6 ++-
.../apache/calcite/test/MaterializationTest.java | 4 ++
.../test/MaterializedViewRelOptRulesTest.java | 13 ++++++
.../calcite/test/schemata/hr/NullableTest.java | 50 ++++++++++++++++++++++
4 files changed, 71 insertions(+), 2 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
index 2068305321..4688a4bb7a 100644
--- a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
+++ b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
@@ -443,7 +443,8 @@ public class SubstitutionVisitor {
for (RexNode disjunction : disjunctions) {
switch (disjunction.getKind()) {
case LITERAL:
- if (!RexLiteral.booleanValue(disjunction)) {
+ if (!RexLiteral.isNullLiteral(disjunction)
+ && !RexLiteral.booleanValue(disjunction)) {
return false;
}
break;
@@ -454,7 +455,8 @@ public class SubstitutionVisitor {
for (RexNode disjunction : notDisjunctions) {
switch (disjunction.getKind()) {
case LITERAL:
- if (RexLiteral.booleanValue(disjunction)) {
+ if (!RexLiteral.isNullLiteral(disjunction)
+ && RexLiteral.booleanValue(disjunction)) {
return false;
}
break;
diff --git
a/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
b/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
index 9e4aad39fe..c9333a78d3 100644
--- a/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
+++ b/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
@@ -35,6 +35,7 @@ import org.apache.calcite.test.schemata.hr.Employee;
import org.apache.calcite.test.schemata.hr.Event;
import org.apache.calcite.test.schemata.hr.HrSchema;
import org.apache.calcite.test.schemata.hr.Location;
+import org.apache.calcite.test.schemata.hr.NullableTest;
import org.apache.calcite.util.JsonBuilder;
import org.apache.calcite.util.Smalls;
import org.apache.calcite.util.TryThreadLocal;
@@ -416,6 +417,9 @@ public class MaterializationTest {
new Dependent(10, "Michael"),
new Dependent(10, "Jane"),
};
+ public final NullableTest[] nullables = {
+ new NullableTest(null, null, 1),
+ };
public final Dependent[] locations = {
new Dependent(10, "San Francisco"),
new Dependent(20, "San Diego"),
diff --git
a/core/src/test/java/org/apache/calcite/test/MaterializedViewRelOptRulesTest.java
b/core/src/test/java/org/apache/calcite/test/MaterializedViewRelOptRulesTest.java
index ccbb851412..d15fdbeafa 100644
---
a/core/src/test/java/org/apache/calcite/test/MaterializedViewRelOptRulesTest.java
+++
b/core/src/test/java/org/apache/calcite/test/MaterializedViewRelOptRulesTest.java
@@ -1227,4 +1227,17 @@ class MaterializedViewRelOptRulesTest {
+ " EnumerableTableScan(table=[[hr, MV0]]")
.ok();
}
+
+ @Test public void testNpeInSplitFilterOfSubstitutionVisitor() {
+ sql("select \"col1\", \"col2\""
+ + " from \"nullables\""
+ + " where \"col1\" <> \"col2\" and \"col3\" = 1",
+ "select \"col1\", \"col2\""
+ + " from \"nullables\""
+ + " where \"col1\" = \"col2\" and \"col3\" = 1")
+ .checkingThatResultContains(""
+ + "EnumerableCalc(expr#0..2=[{inputs}], expr#3=[=($t0, $t1)],
expr#4=[CAST($t2):INTEGER NOT NULL], expr#5=[1], expr#6=[=($t4, $t5)],
expr#7=[AND($t3, $t6)], proj#0..1=[{exprs}], $condition=[$t7])\n"
+ + " EnumerableTableScan(table=[[hr, nullables]])")
+ .ok();
+ }
}
diff --git
a/testkit/src/main/java/org/apache/calcite/test/schemata/hr/NullableTest.java
b/testkit/src/main/java/org/apache/calcite/test/schemata/hr/NullableTest.java
new file mode 100644
index 0000000000..db7da76f93
--- /dev/null
+++
b/testkit/src/main/java/org/apache/calcite/test/schemata/hr/NullableTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.test.schemata.hr;
+
+import java.util.Objects;
+
+/**
+ * A table model that contains nullable columns.
+ */
+public class NullableTest {
+ public final Integer col1;
+ public final Integer col2;
+ public final int col3;
+
+ public NullableTest(Integer col1, Integer col2, int col3) {
+ this.col1 = col1;
+ this.col2 = col2;
+ this.col3 = col3;
+ }
+
+ @Override public String toString() {
+ return "DependentNullable [col1: " + col1 + ", col2: " + col2 + ", col3: "
+ col3 + "]";
+ }
+
+ @Override public boolean equals(Object obj) {
+ return obj == this
+ || obj instanceof NullableTest
+ && Objects.equals(col1, ((NullableTest) obj).col1)
+ && Objects.equals(col2, ((NullableTest) obj).col2)
+ && col3 == ((NullableTest) obj).col3;
+ }
+
+ @Override public int hashCode() {
+ return Objects.hash(col1, col2, col3);
+ }
+}