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 feab5132fcd IGNITE-22992 SQL Calcite: Refactor BaseQueryContext.Builder#frameworkConfig - Fixes #11479. feab5132fcd is described below commit feab5132fcd5b2c940d10836646c9f80ebb9b282 Author: Aleksey Plekhanov <plehanov.a...@gmail.com> AuthorDate: Thu Aug 15 16:52:30 2024 +0300 IGNITE-22992 SQL Calcite: Refactor BaseQueryContext.Builder#frameworkConfig - Fixes #11479. Signed-off-by: Aleksey Plekhanov <plehanov.a...@gmail.com> --- .../processors/query/calcite/RootQuery.java | 13 +- .../query/calcite/exec/ExecutionServiceImpl.java | 8 +- .../query/calcite/prepare/BaseQueryContext.java | 29 ++++- .../calcite/exec/LogicalRelImplementorTest.java | 8 +- .../query/calcite/planner/AbstractPlannerTest.java | 20 ++-- .../query/calcite/planner/PlannerTest.java | 132 ++++----------------- 6 files changed, 66 insertions(+), 144 deletions(-) diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/RootQuery.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/RootQuery.java index e67e7f98435..242e355d22c 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/RootQuery.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/RootQuery.java @@ -30,7 +30,6 @@ import java.util.stream.Collectors; import org.apache.calcite.plan.Context; import org.apache.calcite.schema.SchemaPlus; import org.apache.calcite.tools.FrameworkConfig; -import org.apache.calcite.tools.Frameworks; import org.apache.calcite.util.CancelFlag; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; @@ -58,8 +57,6 @@ import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; import org.jetbrains.annotations.Nullable; -import static org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor.FRAMEWORK_CONFIG; - /** * The RootQuery is created on the query initiator (originator) node as the first step of a query run; * It contains the information about query state, contexts, remote fragments; @@ -142,16 +139,10 @@ public class RootQuery<RowT> extends Query<RowT> implements TrackableQuery { FrameworkConfig frameworkCfg = qryCtx != null ? qryCtx.unwrap(FrameworkConfig.class) : null; - if (frameworkCfg == null) - frameworkCfg = FRAMEWORK_CONFIG; - ctx = BaseQueryContext.builder() .parentContext(parent) - .frameworkConfig( - Frameworks.newConfigBuilder(frameworkCfg) - .defaultSchema(schema) - .build() - ) + .frameworkConfig(frameworkCfg) + .defaultSchema(schema) .local(isLocal) .forcedJoinOrder(forcedJoinOrder) .partitions(parts) diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java index 20d6c146f31..bca13901aaf 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java @@ -31,7 +31,6 @@ import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.rel.core.TableModify; import org.apache.calcite.sql.SqlInsert; import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.tools.Frameworks; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.cache.query.FieldsQueryCursor; @@ -119,7 +118,6 @@ import org.jetbrains.annotations.Nullable; import static java.util.Collections.singletonList; import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_OBJECT_READ; -import static org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor.FRAMEWORK_CONFIG; import static org.apache.ignite.internal.processors.query.calcite.externalize.RelJsonReader.fromJson; /** @@ -481,11 +479,7 @@ public class ExecutionServiceImpl<Row> extends AbstractService implements Execut private BaseQueryContext createQueryContext(Context parent, @Nullable String schema) { return BaseQueryContext.builder() .parentContext(parent) - .frameworkConfig( - Frameworks.newConfigBuilder(FRAMEWORK_CONFIG) - .defaultSchema(schemaHolder().schema(schema)) - .build() - ) + .defaultSchema(schemaHolder().schema(schema)) .logger(log) .build(); } diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/BaseQueryContext.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/BaseQueryContext.java index 2f1e1bb5845..22605e716da 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/BaseQueryContext.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/BaseQueryContext.java @@ -52,8 +52,10 @@ import org.apache.ignite.internal.processors.query.calcite.metadata.cost.IgniteC import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; import org.apache.ignite.logger.NullLogger; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import static org.apache.calcite.tools.Frameworks.createRootSchema; +import static org.apache.calcite.tools.Frameworks.newConfigBuilder; import static org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor.FRAMEWORK_CONFIG; /** @@ -335,8 +337,31 @@ public final class BaseQueryContext extends AbstractQueryContext { * @param frameworkCfg Framework config. * @return Builder for chaining. */ - public Builder frameworkConfig(@NotNull FrameworkConfig frameworkCfg) { - this.frameworkCfg = frameworkCfg; + public Builder frameworkConfig(@Nullable FrameworkConfig frameworkCfg) { + if (frameworkCfg == null) + return this; + + if (this.frameworkCfg != EMPTY_CONFIG) { + // Schema was set explicitely earlier. + SchemaPlus schema = this.frameworkCfg.getDefaultSchema(); + + this.frameworkCfg = newConfigBuilder(frameworkCfg).defaultSchema(schema).build(); + } + else + this.frameworkCfg = frameworkCfg; + + return this; + } + + /** + * @param schema Default schema. + * @return Builder for chaining. + */ + public Builder defaultSchema(SchemaPlus schema) { + frameworkCfg = newConfigBuilder(frameworkCfg) + .defaultSchema(schema) + .build(); + return this; } diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementorTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementorTest.java index 8105a9da3fd..209eb75195c 100644 --- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementorTest.java +++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementorTest.java @@ -62,8 +62,6 @@ import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.junit.Test; import static org.apache.calcite.tools.Frameworks.createRootSchema; -import static org.apache.calcite.tools.Frameworks.newConfigBuilder; -import static org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor.FRAMEWORK_CONFIG; /** * Test LogicalRelImplementor class. @@ -110,11 +108,7 @@ public class LogicalRelImplementorTest extends GridCommonAbstractTest { publicSchema.addTable("TBL", tbl); qctx = BaseQueryContext.builder() - .frameworkConfig( - newConfigBuilder(FRAMEWORK_CONFIG) - .defaultSchema(createRootSchema(false).add(publicSchema.getName(), publicSchema)) - .build() - ) + .defaultSchema(createRootSchema(false).add(publicSchema.getName(), publicSchema)) .logger(log) .build(); diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java index 72db75bedcc..6f5c351810c 100644 --- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java +++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java @@ -47,6 +47,7 @@ import org.apache.calcite.schema.SchemaPlus; import org.apache.calcite.sql.SqlExplainLevel; import org.apache.calcite.sql.SqlFunction; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql2rel.InitializerContext; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.Util; @@ -101,8 +102,6 @@ import org.junit.Before; import org.mockito.Mockito; import static org.apache.calcite.tools.Frameworks.createRootSchema; -import static org.apache.calcite.tools.Frameworks.newConfigBuilder; -import static org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor.FRAMEWORK_CONFIG; import static org.apache.ignite.internal.processors.query.calcite.externalize.RelJsonWriter.toJson; /** @@ -645,8 +644,15 @@ public abstract class AbstractPlannerTest extends GridCommonAbstractTest { RelDataTypeFactory.Builder b = new RelDataTypeFactory.Builder(TYPE_FACTORY); - for (int i = 0; i < fields.length; i += 2) - b.add((String)fields[i], TYPE_FACTORY.createJavaType((Class<?>)fields[i + 1])); + for (int i = 0; i < fields.length; i += 2) { + if (!(fields[i + 1] instanceof Class) && !(fields[i + 1] instanceof SqlTypeName)) + throw new IllegalArgumentException("'fields[" + i + "]' should be a class or a SqlTypeName"); + + RelDataType type = fields[i + 1] instanceof Class ? TYPE_FACTORY.createJavaType((Class<?>)fields[i + 1]) : + TYPE_FACTORY.createSqlType((SqlTypeName)fields[i + 1]); + + b.add((String)fields[i], type); + } return new TestTable(name, b.build(), size) { @Override public IgniteDistribution distribution() { @@ -683,11 +689,7 @@ public abstract class AbstractPlannerTest extends GridCommonAbstractTest { } return BaseQueryContext.builder() - .frameworkConfig( - newConfigBuilder(FRAMEWORK_CONFIG) - .defaultSchema(dfltSchema) - .build() - ) + .defaultSchema(dfltSchema) .logger(lsnrLog) .build(); } diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlannerTest.java index 2bc2761a03b..39e956ae9a1 100644 --- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlannerTest.java +++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlannerTest.java @@ -24,13 +24,11 @@ import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; import org.apache.calcite.plan.RelOptUtil; -import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelNode; -import org.apache.calcite.rel.RelRoot; import org.apache.calcite.rel.RelVisitor; +import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.schema.SchemaPlus; -import org.apache.calcite.sql.SqlNode; import org.apache.calcite.util.ImmutableBitSet; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; @@ -50,23 +48,19 @@ import org.apache.ignite.internal.processors.query.calcite.message.MessageServic import org.apache.ignite.internal.processors.query.calcite.message.TestIoManager; import org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup; import org.apache.ignite.internal.processors.query.calcite.metadata.FragmentDescription; -import org.apache.ignite.internal.processors.query.calcite.metadata.cost.IgniteCostFactory; import org.apache.ignite.internal.processors.query.calcite.prepare.BaseQueryContext; import org.apache.ignite.internal.processors.query.calcite.prepare.ExecutionPlan; import org.apache.ignite.internal.processors.query.calcite.prepare.Fragment; -import org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePlanner; import org.apache.ignite.internal.processors.query.calcite.prepare.MappingQueryContext; import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepPlan; import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepQueryPlan; -import org.apache.ignite.internal.processors.query.calcite.prepare.PlannerPhase; import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext; import org.apache.ignite.internal.processors.query.calcite.prepare.QueryTemplate; import org.apache.ignite.internal.processors.query.calcite.prepare.Splitter; -import org.apache.ignite.internal.processors.query.calcite.rel.IgniteConvention; +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin; import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter; import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel; import org.apache.ignite.internal.processors.query.calcite.schema.IgniteSchema; -import org.apache.ignite.internal.processors.query.calcite.trait.CorrelationTrait; import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution; import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions; import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory; @@ -79,10 +73,10 @@ import org.apache.ignite.thread.IgniteStripedThreadPoolExecutor; import org.junit.Assert; import org.junit.Test; +import static org.apache.calcite.sql.type.SqlTypeName.INTEGER; +import static org.apache.calcite.sql.type.SqlTypeName.VARCHAR; import static org.apache.calcite.tools.Frameworks.createRootSchema; -import static org.apache.calcite.tools.Frameworks.newConfigBuilder; import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_THREAD_KEEP_ALIVE_TIME; -import static org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor.FRAMEWORK_CONFIG; /** * @@ -303,9 +297,7 @@ public class PlannerTest extends AbstractPlannerTest { BaseQueryContext qctx = BaseQueryContext.builder() .logger(log) - .frameworkConfig(newConfigBuilder(FRAMEWORK_CONFIG) - .defaultSchema(schema) - .build()) + .defaultSchema(schema) .build(); PlanningContext ctx = PlanningContext.builder() @@ -780,105 +772,29 @@ public class PlannerTest extends AbstractPlannerTest { */ @Test public void testJoinPushExpressionRule() throws Exception { - IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE); - - TestTable emp = new TestTable( - new RelDataTypeFactory.Builder(f) - .add("ID", f.createJavaType(Integer.class)) - .add("NAME", f.createJavaType(String.class)) - .add("DEPTNO", f.createJavaType(Integer.class)) - .build()) { - - @Override public IgniteDistribution distribution() { - return IgniteDistributions.broadcast(); - } - }; - - TestTable dept = new TestTable( - new RelDataTypeFactory.Builder(f) - .add("DEPTNO", f.createJavaType(Integer.class)) - .add("NAME", f.createJavaType(String.class)) - .build()) { - - @Override public IgniteDistribution distribution() { - return IgniteDistributions.broadcast(); - } - }; - - IgniteSchema publicSchema = new IgniteSchema("PUBLIC"); - - publicSchema.addTable("EMP", emp); - publicSchema.addTable("DEPT", dept); - - SchemaPlus schema = createRootSchema(false) - .add("PUBLIC", publicSchema); + IgniteSchema publicSchema = createSchema( + createTable("EMP", 100, IgniteDistributions.broadcast(), + "ID", INTEGER, "NAME", VARCHAR, "DEPTNO", INTEGER), + createTable("DEPT", 10, IgniteDistributions.broadcast(), + "DEPTNO", INTEGER, "NAME", VARCHAR) + ); - String sql = "select d.deptno, e.deptno " + + String sql = "select /*+ CNL_JOIN */ d.deptno, e.deptno " + "from dept d, emp e " + "where d.deptno + e.deptno = 2"; - PlanningContext ctx = PlanningContext.builder() - .parentContext(BaseQueryContext.builder() - .frameworkConfig(newConfigBuilder(FRAMEWORK_CONFIG) - .defaultSchema(schema) - .costFactory(new IgniteCostFactory(1, 100, 1, 1)) - .build()) - .logger(log) - .build() - ) - .query(sql) - .build(); - - RelRoot relRoot; - - try (IgnitePlanner planner = ctx.planner()) { - assertNotNull(planner); - - String qry = ctx.query(); - - assertNotNull(qry); - - // Parse - SqlNode sqlNode = planner.parse(qry); - - // Validate - sqlNode = planner.validate(sqlNode); - - // Convert to Relational operators graph - relRoot = planner.rel(sqlNode); - - RelNode rel = relRoot.rel; - - assertNotNull(rel); - assertEquals("" + - "LogicalProject(DEPTNO=[$0], DEPTNO0=[$4])\n" + - " LogicalFilter(condition=[=(CAST(+($0, $4)):INTEGER, 2)])\n" + - " LogicalJoin(condition=[true], joinType=[inner])\n" + - " IgniteLogicalTableScan(table=[[PUBLIC, DEPT]])\n" + - " IgniteLogicalTableScan(table=[[PUBLIC, EMP]])\n", - RelOptUtil.toString(rel)); - - // Transformation chain - RelTraitSet desired = rel.getCluster().traitSet() - .replace(IgniteConvention.INSTANCE) - .replace(IgniteDistributions.single()) - .replace(CorrelationTrait.UNCORRELATED) - .simplify(); - - IgniteRel phys = planner.transform(PlannerPhase.OPTIMIZATION, desired, rel); - - assertNotNull(phys); - assertEquals( - "Invalid plan:\n" + RelOptUtil.toString(phys), - "IgniteProject(DEPTNO=[$3], DEPTNO0=[$2])\n" + - " IgniteCorrelatedNestedLoopJoin(condition=[=(CAST(+($3, $2)):INTEGER, 2)], joinType=[inner], " + - "variablesSet=[[$cor2]], correlationVariables=[[$cor2]])\n" + - " IgniteTableScan(table=[[PUBLIC, EMP]])\n" + - " IgniteTableScan(table=[[PUBLIC, DEPT]], filters=[=(CAST(+($t0, $cor2.DEPTNO)):INTEGER, 2)])\n", - RelOptUtil.toString(phys)); - - checkSplitAndSerialization(phys, publicSchema); - } + assertPlan(sql, publicSchema, isInstanceOf(IgniteCorrelatedNestedLoopJoin.class) + .and(cnlj -> "=(+($0, $1), 2)".equals(cnlj.getCondition().toString())) + .and(cnlj -> cnlj.getJoinType() == JoinRelType.INNER) + .and(cnlj -> cnlj.getVariablesSet().size() == 1) + .and(input(0, isTableScan("DEPT") + .and(t -> t.requiredColumns().equals(ImmutableBitSet.of(0))) + )) + .and(input(1, isTableScan("EMP") + .and(t -> t.requiredColumns().equals(ImmutableBitSet.of(2))) + .and(t -> "=(+($cor1.DEPTNO, $t0), 2)".equals(t.condition().toString())) + )) + ); } /** */