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 6863dfaccce IGNITE-25357 SQL Calcite: Fixed assertion on planning for
filter with double correlate - Fixes #12183.
6863dfaccce is described below
commit 6863dfaccce5d4ba4c42e3bf2d4747eceb35edac
Author: Vladimir Steshin <[email protected]>
AuthorDate: Mon Jul 14 18:37:59 2025 +0500
IGNITE-25357 SQL Calcite: Fixed assertion on planning for filter with
double correlate - Fixes #12183.
Signed-off-by: Aleksey Plekhanov <[email protected]>
---
.../query/calcite/CalciteQueryProcessor.java | 3 ++
.../integration/CorrelatesIntegrationTest.java | 44 +++++++++++++++++++++-
.../planner/CorrelatedSubqueryPlannerTest.java | 34 +++++++++++++++++
3 files changed, 79 insertions(+), 2 deletions(-)
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java
index da4a02cd857..123fdad34d5 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java
@@ -33,6 +33,7 @@ import org.apache.calcite.plan.Contexts;
import org.apache.calcite.plan.ConventionTraitDef;
import org.apache.calcite.plan.RelTraitDef;
import org.apache.calcite.rel.RelCollationTraitDef;
+import org.apache.calcite.rel.core.Correlate;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlDdl;
@@ -144,6 +145,8 @@ public class CalciteQueryProcessor extends
GridProcessorAdapter implements Query
// See Apache Calcite ticket for more information, assertion is
incorrect.
// FRAMEWORK_CONFIG initialize SqlToRelConverter class. Assertions
should be disabled before class initialization.
SqlToRelConverter.class.getClassLoader().setClassAssertionStatus(SqlToRelConverter.class.getName(),
false);
+ // TODO Workaround for
https://issues.apache.org/jira/browse/CALCITE-5421 and
https://issues.apache.org/jira/browse/CALCITE-7034
+
Correlate.class.getClassLoader().setClassAssertionStatus(Correlate.class.getName(),
false);
}
/**
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CorrelatesIntegrationTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CorrelatesIntegrationTest.java
index 47a00cf07b0..bc7df8a544a 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CorrelatesIntegrationTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CorrelatesIntegrationTest.java
@@ -17,6 +17,9 @@
package org.apache.ignite.internal.processors.query.calcite.integration;
+import java.sql.Date;
+import java.time.Instant;
+import java.util.UUID;
import org.apache.ignite.internal.processors.query.calcite.QueryChecker;
import org.junit.Test;
@@ -126,15 +129,52 @@ public class CorrelatesIntegrationTest extends
AbstractBasicIntegrationTransacti
/** */
@Test
public void testTwoTablesCorrelatedSubquery() {
- sql("CREATE TABLE T1(ID INT, REF INT) WITH " + atomicity());
+ sql("CREATE TABLE T1(ID INT, PADDING1 VARCHAR, PADDING2 DATE, PADDING3
UUID, REF INT) WITH " + atomicity());
sql("CREATE TABLE T2(ID INT, REF INT) WITH " + atomicity());
sql("CREATE TABLE T3(ID1 INT, ID2 INT) WITH " + atomicity());
- sql("INSERT INTO T1 VALUES(1, 1)");
+ sql("INSERT INTO T1 VALUES(1, 'str', ?, ?, 1)",
Date.from(Instant.now()), UUID.randomUUID());
sql("INSERT INTO T2 VALUES(1, 1)");
sql("INSERT INTO T3 VALUES(1, 1)");
assertQuery("SELECT T1.ID, T2.ID FROM T1 JOIN T2 ON (T1.ID = T2.ID) " +
"WHERE EXISTS (SELECT 1 FROM T3 WHERE T3.ID1 = T1.REF AND T3.ID2 =
T2.REF)").returns(1, 1).check();
}
+
+ /** */
+ @Test
+ public void testPaddedCorrelateInSecondFilterSubquery() {
+ // The padding columns keeps row size bigger than other operators and
field access indexes so that the correlated
+ // column must be remapped correctly.
+ sql("CREATE TABLE T1(ID1 INT, PADDING1 VARCHAR, PADDING2 DATE,
PADDING3 UUID, REF1 INT) WITH " + atomicity());
+ sql("CREATE TABLE T2(ID2 INT, REF2 INT) WITH " + atomicity());
+ sql("CREATE TABLE T3(ID3 INT, REF3 INT) WITH " + atomicity());
+
+ for (int i = 1; i <= 10; ++i)
+ sql("INSERT INTO T1 VALUES(?, ?, ?, ?, ?)", i, "str_" + i,
Date.from(Instant.now()), UUID.randomUUID(), i * 10);
+
+ for (int i = 1; i <= 7; ++i)
+ sql("INSERT INTO T2 VALUES(?, ?)", i * 100, i * 10);
+
+ for (int i = 3; i <= 10; ++i)
+ sql("INSERT INTO T3 VALUES(?, ?)", i * 1000, i * 10);
+
+ // IN
+ assertQuery("SELECT ID1 FROM T1 WHERE REF1 IN " +
+ "(SELECT REF2 FROM T2 WHERE REF2 IN (SELECT REF3 FROM T3 WHERE
REF3 = T1.REF1))")
+ .returns(3).returns(4).returns(5).returns(6).returns(7)
+ .check();
+
+ // ANY
+ assertQuery("SELECT ID1 FROM T1 WHERE REF1 IN " +
+ "(SELECT REF2 FROM T2 WHERE REF2 < ANY (SELECT REF3 FROM T3 WHERE
REF3 != T1.REF1))")
+
.returns(1).returns(2).returns(3).returns(4).returns(5).returns(6).returns(7)
+ .check();
+
+ // EXISTS
+ assertQuery("SELECT ID1 FROM T1 WHERE REF1 IN " +
+ "(SELECT REF2 FROM T2 WHERE NOT EXISTS (SELECT REF3 FROM T3 WHERE
REF3 = T1.REF1))")
+ .returns(1).returns(2)
+ .check();
+ }
}
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/CorrelatedSubqueryPlannerTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/CorrelatedSubqueryPlannerTest.java
index 0f074a5baaf..2b3e17264c2 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/CorrelatedSubqueryPlannerTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/CorrelatedSubqueryPlannerTest.java
@@ -17,9 +17,11 @@
package org.apache.ignite.internal.processors.query.calcite.planner;
+import java.sql.Date;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.UUID;
import java.util.function.Predicate;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Filter;
@@ -47,6 +49,7 @@ import
org.apache.ignite.internal.processors.query.calcite.rel.agg.IgniteColocat
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteSchema;
import
org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
import org.apache.ignite.internal.processors.query.calcite.util.RexUtils;
+import org.apache.ignite.internal.util.typedef.F;
import org.junit.Test;
/** Tests to verify correlated subquery planning. */
@@ -95,6 +98,37 @@ public class CorrelatedSubqueryPlannerTest extends
AbstractPlannerTest {
);
}
+ /** */
+ @Test
+ public void testPaddedCorrelateInSecondFilterSubquery() throws Exception {
+ IgniteSchema schema = createSchema(
+ createTable("T1", IgniteDistributions.single(), "ID1",
Integer.class, "PADDING1", String.class,
+ "PADDING2", Date.class, "PADDING3", UUID.class, "REF1",
Integer.class),
+ createTable("T2", IgniteDistributions.single(), "ID2",
Integer.class, "REF2", Integer.class),
+ createTable("T3", IgniteDistributions.single(), "ID3",
Integer.class, "REF3", Integer.class)
+ );
+
+ String qTpl = "SELECT ID1 FROM T1 WHERE REF1 IN (SELECT REF2 FROM T2
WHERE %s" +
+ " (SELECT REF3 FROM T3 WHERE REF3 = T1.REF1))";
+
+ for (String tbl2Filter : F.asList("REF2 IN", "REF2 < ANY", "EXISTS")) {
+ String q = String.format(qTpl, tbl2Filter);
+
+ if (log.isInfoEnabled())
+ log.info(String.format("Test query:\n '%s'", q));
+
+ assertPlan(q, schema,
+
nodeOrAnyChild(isInstanceOf(IgniteCorrelatedNestedLoopJoin.class)
+ .and(cnl -> cnl.getVariablesSet().size() == 1 &&
"$cor0".equals(F.first(cnl.getVariablesSet()).getName()))
+ .and(input(0, nodeOrAnyChild(isTableScan("T1"))))
+ .and(input(1, nodeOrAnyChild(isTableScan("T3")
+ .and(ts -> "=($t0,
$cor0.REF1)".equals(ts.condition().toString())))))
+ .and(input(1, nodeOrAnyChild(isTableScan("T2").and(ts ->
ts.condition() == null))))
+ )
+ );
+ }
+ }
+
/** */
@Test
public void testCorrelatesInJoin() throws Exception {