You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2022/10/19 10:17:24 UTC
[ignite] branch master updated: IGNITE-13024 SQL Calcite: Support complex expressions in index search bounds - Fixes #10317.
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 99bcc7daa2f IGNITE-13024 SQL Calcite: Support complex expressions in index search bounds - Fixes #10317.
99bcc7daa2f is described below
commit 99bcc7daa2f7f69166a4a8a3dcef52005b54be3d
Author: Aleksey Plekhanov <pl...@gmail.com>
AuthorDate: Wed Oct 19 13:15:16 2022 +0300
IGNITE-13024 SQL Calcite: Support complex expressions in index search bounds - Fixes #10317.
Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
.../processors/query/calcite/util/RexUtils.java | 25 +++++++++++++++++++-
.../CalciteBasicSecondaryIndexIntegrationTest.java | 25 ++++++++++++++++++++
.../planner/IndexSearchBoundsPlannerTest.java | 27 ++++++++++++++++++++++
3 files changed, 76 insertions(+), 1 deletion(-)
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 3bfeb4d2839..d32b89e254f 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
@@ -653,7 +653,8 @@ public class RexUtils {
private static boolean idxOpSupports(RexNode op) {
return op instanceof RexLiteral
|| op instanceof RexDynamicParam
- || op instanceof RexFieldAccess;
+ || op instanceof RexFieldAccess
+ || !containsRef(op);
}
/** */
@@ -776,6 +777,28 @@ public class RexUtils {
return cors;
}
+ /** */
+ private static Boolean containsRef(RexNode node) {
+ RexVisitor<Void> v = new RexVisitorImpl<Void>(true) {
+ @Override public Void visitInputRef(RexInputRef inputRef) {
+ throw Util.FoundOne.NULL;
+ }
+
+ @Override public Void visitLocalRef(RexLocalRef locRef) {
+ throw Util.FoundOne.NULL;
+ }
+ };
+
+ try {
+ node.accept(v);
+
+ return false;
+ }
+ catch (Util.FoundOne e) {
+ return true;
+ }
+ }
+
/** Visitor for replacing scan local refs to input refs. */
private static class LocalRefReplacer extends RexShuttle {
/** */
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CalciteBasicSecondaryIndexIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CalciteBasicSecondaryIndexIntegrationTest.java
index 54a62ddec35..31c9e77f404 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CalciteBasicSecondaryIndexIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CalciteBasicSecondaryIndexIntegrationTest.java
@@ -1158,6 +1158,31 @@ public class CalciteBasicSecondaryIndexIntegrationTest extends AbstractBasicInte
.check();
}
+ /**
+ * Test index search bounds on complex index expression.
+ */
+ @Test
+ public void testComplexIndexExpression() {
+ assertQuery("SELECT id FROM Developer WHERE depId BETWEEN ? - 1 AND ? + 1")
+ .withParams(20, 20)
+ .matches(containsIndexScan("PUBLIC", "DEVELOPER", DEPID_IDX))
+ .returns(20)
+ .returns(21)
+ .returns(22)
+ .check();
+
+ assertQuery("SELECT id FROM Birthday WHERE name = SUBSTRING(?::VARCHAR, 1, 4)")
+ .withParams("BachBach")
+ .matches(containsIndexScan("PUBLIC", "BIRTHDAY", NAME_DATE_IDX))
+ .returns(3)
+ .check();
+
+ assertQuery("SELECT id FROM Birthday WHERE name = SUBSTRING(name, 1, 4)")
+ .matches(containsTableScan("PUBLIC", "BIRTHDAY"))
+ .returns(3)
+ .check();
+ }
+
/** */
private static class Developer {
/** */
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/IndexSearchBoundsPlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/IndexSearchBoundsPlannerTest.java
index 6849e3c393a..528565e71c7 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/IndexSearchBoundsPlannerTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/IndexSearchBoundsPlannerTest.java
@@ -423,6 +423,33 @@ public class IndexSearchBoundsPlannerTest extends AbstractPlannerTest {
);
}
+ /** Tests complex bounds expressions. */
+ @Test
+ public void testBoundsComplex() throws Exception {
+ assertBounds("SELECT * FROM TEST WHERE C1 = ? + 10",
+ exact("+(?0, 10)")
+ );
+
+ assertBounds("SELECT * FROM TEST WHERE C1 = 1 AND C2 > SUBSTRING(?::VARCHAR, 1, 2) || '3'",
+ exact(1),
+ range("||(SUBSTRING(?0, 1, 2), _UTF-8'3')", null, false, true)
+ );
+
+ assertBounds("SELECT * FROM TEST WHERE C1 = 1 AND C2 > SUBSTRING(C3::VARCHAR, 1, 2) || '3'",
+ exact(1),
+ empty()
+ );
+
+ assertBounds("SELECT (SELECT C1 FROM TEST t2 WHERE t2.C1 = t1.C1 + t1.C3 * ?) FROM TEST t1",
+ exact("+($cor0.C1, *($cor0.C3, ?0))")
+ );
+
+ assertPlan("SELECT * FROM TEST WHERE C1 = ? + C3", publicSchema, isTableScan("TEST"));
+
+ assertPlan("SELECT (SELECT C1 FROM TEST t2 WHERE t2.C1 < t1.C1 + t2.C1) FROM TEST t1", publicSchema,
+ nodeOrAnyChild(isIndexScan("TEST", "C1C2C3")).negate());
+ }
+
/** String representation of LEAST or CREATEST operator converted to CASE. */
private String leastOrGreatest(boolean least, String val0, String val1, String type) {
return "CASE(OR(IS NULL(" + val0 + "), IS NULL(" + val1 + ")), null:" + type + ", " + (least ? '<' : '>') +