This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new e8e6919ee28 IGNITE-17890 SQL Calcite: Support index scan on boolean
fields - Fixes #10332.
e8e6919ee28 is described below
commit e8e6919ee2833bcdf51588e06134ee90d16fbc7d
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Thu Oct 20 11:32:15 2022 +0300
IGNITE-17890 SQL Calcite: Support index scan on boolean fields - Fixes
#10332.
Signed-off-by: Aleksey Plekhanov <[email protected]>
---
.../processors/query/calcite/util/RexUtils.java | 16 +++++++
.../integration/IndexScanlIntegrationTest.java | 53 ++++++++++++++++++++++
2 files changed, 69 insertions(+)
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/RexUtils.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/RexUtils.java
index d32b89e254f..396be25e579 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/RexUtils.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/RexUtils.java
@@ -82,6 +82,7 @@ import static org.apache.calcite.sql.SqlKind.IS_NOT_NULL;
import static org.apache.calcite.sql.SqlKind.IS_NULL;
import static org.apache.calcite.sql.SqlKind.LESS_THAN;
import static org.apache.calcite.sql.SqlKind.LESS_THAN_OR_EQUAL;
+import static org.apache.calcite.sql.SqlKind.NOT;
import static org.apache.calcite.sql.SqlKind.SEARCH;
/** */
@@ -562,6 +563,8 @@ public class RexUtils {
Map<Integer, List<RexCall>> res = new HashMap<>(conjunctions.size());
for (RexNode rexNode : conjunctions) {
+ rexNode = expandBooleanFieldComparison(rexNode, builder(cluster));
+
if (!isSupportedTreeComparison(rexNode))
continue;
@@ -592,6 +595,19 @@ public class RexUtils {
return res;
}
+ /** */
+ private static RexNode expandBooleanFieldComparison(RexNode rexNode,
RexBuilder builder) {
+ if (rexNode instanceof RexSlot)
+ return builder.makeCall(SqlStdOperatorTable.EQUALS, rexNode,
builder.makeLiteral(true));
+ else if (rexNode instanceof RexCall && rexNode.getKind() == NOT &&
+ ((RexCall)rexNode).getOperands().get(0) instanceof RexSlot) {
+ return builder.makeCall(SqlStdOperatorTable.EQUALS,
((RexCall)rexNode).getOperands().get(0),
+ builder.makeLiteral(false));
+ }
+
+ return rexNode;
+ }
+
/** */
private static RexNode extractRefFromBinary(RexCall call, RelOptCluster
cluster) {
assert isBinaryComparison(call);
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/IndexScanlIntegrationTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/IndexScanlIntegrationTest.java
index 53457074fd5..799a0fc6663 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/IndexScanlIntegrationTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/IndexScanlIntegrationTest.java
@@ -129,4 +129,57 @@ public class IndexScanlIntegrationTest extends
AbstractBasicIntegrationTest {
.returns("emp60")
.check();
}
+
+ /** */
+ @Test
+ public void testScanBooleanField() {
+ executeSql("CREATE TABLE t(i INTEGER, b BOOLEAN)");
+ executeSql("INSERT INTO t VALUES (0, TRUE), (1, TRUE), (2, FALSE), (3,
FALSE), (4, null)");
+ executeSql("CREATE INDEX t_idx ON t(b)");
+
+ assertQuery("SELECT i FROM t WHERE b = TRUE")
+ .matches(QueryChecker.containsIndexScan("PUBLIC", "T", "T_IDX"))
+ .returns(0)
+ .returns(1)
+ .check();
+
+ assertQuery("SELECT i FROM t WHERE b = FALSE")
+ .matches(QueryChecker.containsIndexScan("PUBLIC", "T", "T_IDX"))
+ .returns(2)
+ .returns(3)
+ .check();
+
+ assertQuery("SELECT i FROM t WHERE b IS TRUE")
+ .matches(QueryChecker.containsIndexScan("PUBLIC", "T", "T_IDX"))
+ .returns(0)
+ .returns(1)
+ .check();
+
+ assertQuery("SELECT i FROM t WHERE b IS FALSE")
+ .matches(QueryChecker.containsIndexScan("PUBLIC", "T", "T_IDX"))
+ .returns(2)
+ .returns(3)
+ .check();
+
+ // Support index scans for IS TRUE, IS FALSE but not for IS NOT TRUE,
IS NOT FALSE, since it requeres multi
+ // bounds scan and may not be effective.
+ assertQuery("SELECT i FROM t WHERE b IS NOT TRUE")
+ .matches(QueryChecker.containsTableScan("PUBLIC", "T"))
+ .returns(2)
+ .returns(3)
+ .returns(4)
+ .check();
+
+ assertQuery("SELECT i FROM t WHERE b IS NOT FALSE")
+ .matches(QueryChecker.containsTableScan("PUBLIC", "T"))
+ .returns(0)
+ .returns(1)
+ .returns(4)
+ .check();
+
+ assertQuery("SELECT i FROM t WHERE b IS NULL")
+ .matches(QueryChecker.containsIndexScan("PUBLIC", "T", "T_IDX"))
+ .returns(4)
+ .check();
+ }
}