This is an automated email from the ASF dual-hosted git repository.
ppa pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new a4642da0d3 IGNITE-17709 Sql. Table hints support (#1101)
a4642da0d3 is described below
commit a4642da0d3678167a3efc083dd95e7e980ee44fd
Author: Pavel Pereslegin <[email protected]>
AuthorDate: Fri Sep 23 18:31:39 2022 +0300
IGNITE-17709 Sql. Table hints support (#1101)
---
.../internal/sql/engine/rel/IgniteTableScan.java | 22 ++++++--
.../engine/rel/logical/IgniteLogicalTableScan.java | 14 ++++-
.../sql/engine/rule/LogicalScanConverterRule.java | 4 +-
.../engine/rule/logical/FilterScanMergeRule.java | 2 +-
.../engine/rule/logical/LogicalOrToUnionRule.java | 1 +
.../engine/rule/logical/ProjectScanMergeRule.java | 1 +
.../internal/sql/engine/schema/IgniteTable.java | 6 ++-
.../sql/engine/schema/IgniteTableImpl.java | 4 +-
.../sql/engine/schema/InternalIgniteTable.java | 6 ++-
.../sql/engine/planner/AbstractPlannerTest.java | 62 ++++++++++++++++++----
.../internal/sql/engine/planner/PlannerTest.java | 32 +++++++++++
11 files changed, 130 insertions(+), 24 deletions(-)
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
index 89273a7d41..3bd54d2f77 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
@@ -25,6 +25,7 @@ import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.hint.RelHint;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.util.ImmutableBitSet;
import org.jetbrains.annotations.Nullable;
@@ -63,7 +64,7 @@ public class IgniteTableScan extends
ProjectableFilterableTableScan implements S
RelTraitSet traits,
RelOptTable tbl
) {
- this(cluster, traits, tbl, null, null, null);
+ this(cluster, traits, tbl, List.of(), null, null, null);
}
/**
@@ -72,6 +73,7 @@ public class IgniteTableScan extends
ProjectableFilterableTableScan implements S
* @param cluster Cluster that this relational expression belongs
to.
* @param traits Traits of this relational expression.
* @param tbl Table definition.
+ * @param hints Table hints.
* @param proj Projects.
* @param cond Filters.
* @param requiredColumns Participating columns.
@@ -80,18 +82,21 @@ public class IgniteTableScan extends
ProjectableFilterableTableScan implements S
RelOptCluster cluster,
RelTraitSet traits,
RelOptTable tbl,
+ List<RelHint> hints,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
@Nullable ImmutableBitSet requiredColumns
) {
- this(-1L, cluster, traits, tbl, proj, cond, requiredColumns);
+ this(-1L, cluster, traits, hints, tbl, proj, cond, requiredColumns);
}
/**
* Creates a TableScan.
*
+ * @param sourceId Source id.
* @param cluster Cluster that this relational expression belongs
to.
* @param traits Traits of this relational expression.
+ * @param hints Table hints.
* @param tbl Table definition.
* @param proj Projects.
* @param cond Filters.
@@ -101,12 +106,13 @@ public class IgniteTableScan extends
ProjectableFilterableTableScan implements S
long sourceId,
RelOptCluster cluster,
RelTraitSet traits,
+ List<RelHint> hints,
RelOptTable tbl,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
@Nullable ImmutableBitSet requiredColumns
) {
- super(cluster, traits, List.of(), tbl, proj, cond, requiredColumns);
+ super(cluster, traits, hints, tbl, proj, cond, requiredColumns);
this.sourceId = sourceId;
}
@@ -134,12 +140,18 @@ public class IgniteTableScan extends
ProjectableFilterableTableScan implements S
/** {@inheritDoc} */
@Override
public IgniteRel clone(long sourceId) {
- return new IgniteTableScan(sourceId, getCluster(), getTraitSet(),
getTable(), projects, condition, requiredColumns);
+ return new IgniteTableScan(sourceId, getCluster(), getTraitSet(),
getHints(), getTable(), projects, condition, requiredColumns);
}
/** {@inheritDoc} */
@Override
public IgniteRel clone(RelOptCluster cluster, List<IgniteRel> inputs) {
- return new IgniteTableScan(sourceId, cluster, getTraitSet(),
getTable(), projects, condition, requiredColumns);
+ return new IgniteTableScan(sourceId, cluster, getTraitSet(),
getHints(), getTable(), projects, condition, requiredColumns);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IgniteTableScan withHints(List<RelHint> hintList) {
+ return new IgniteTableScan(sourceId, getCluster(), getTraitSet(),
hintList, getTable(), projects, condition, requiredColumns);
}
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
index 31c75d199d..32d76a1264 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
@@ -21,6 +21,7 @@ import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.hint.RelHint;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.util.ImmutableBitSet;
import
org.apache.ignite.internal.sql.engine.rel.ProjectableFilterableTableScan;
@@ -35,12 +36,13 @@ public class IgniteLogicalTableScan extends
ProjectableFilterableTableScan {
public static IgniteLogicalTableScan create(
RelOptCluster cluster,
RelTraitSet traits,
+ List<RelHint> hints,
RelOptTable tbl,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
@Nullable ImmutableBitSet requiredColumns
) {
- return new IgniteLogicalTableScan(cluster, traits, tbl, proj, cond,
requiredColumns);
+ return new IgniteLogicalTableScan(cluster, traits, hints, tbl, proj,
cond, requiredColumns);
}
/**
@@ -48,6 +50,7 @@ public class IgniteLogicalTableScan extends
ProjectableFilterableTableScan {
*
* @param cluster Cluster that this relational expression belongs
to.
* @param traits Traits of this relational expression.
+ * @param hints Table hints.
* @param tbl Table definition.
* @param proj Projects.
* @param cond Filters.
@@ -56,11 +59,18 @@ public class IgniteLogicalTableScan extends
ProjectableFilterableTableScan {
private IgniteLogicalTableScan(
RelOptCluster cluster,
RelTraitSet traits,
+ List<RelHint> hints,
RelOptTable tbl,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
@Nullable ImmutableBitSet requiredColumns
) {
- super(cluster, traits, List.of(), tbl, proj, cond, requiredColumns);
+ super(cluster, traits, hints, tbl, proj, cond, requiredColumns);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IgniteLogicalTableScan withHints(List<RelHint> hintList) {
+ return new IgniteLogicalTableScan(getCluster(), getTraitSet(),
hintList, getTable(), projects, condition, requiredColumns);
}
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/LogicalScanConverterRule.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/LogicalScanConverterRule.java
index 0c3ef47344..98bb3fb39d 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/LogicalScanConverterRule.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/LogicalScanConverterRule.java
@@ -145,8 +145,8 @@ public abstract class LogicalScanConverterRule<T extends
ProjectableFilterableTa
.replace(distribution)
.replace(corrIds.isEmpty() ?
CorrelationTrait.UNCORRELATED : CorrelationTrait.correlations(corrIds));
- return new IgniteTableScan(rel.getCluster(), traits,
- rel.getTable(), rel.projects(), rel.condition(),
rel.requiredColumns());
+ return new IgniteTableScan(rel.getCluster(), traits,
rel.getTable(), rel.getHints(),
+ rel.projects(), rel.condition(),
rel.requiredColumns());
}
};
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/FilterScanMergeRule.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/FilterScanMergeRule.java
index 33622f2809..db2b6fc523 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/FilterScanMergeRule.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/FilterScanMergeRule.java
@@ -127,7 +127,7 @@ public abstract class FilterScanMergeRule<T extends
ProjectableFilterableTableSc
RelTraitSet traits,
RexNode cond
) {
- return IgniteLogicalTableScan.create(cluster, traits,
scan.getTable(), scan.projects(),
+ return IgniteLogicalTableScan.create(cluster, traits,
scan.getHints(), scan.getTable(), scan.projects(),
cond, scan.requiredColumns());
}
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/LogicalOrToUnionRule.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/LogicalOrToUnionRule.java
index 32746beeed..745fe4d774 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/LogicalOrToUnionRule.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/LogicalOrToUnionRule.java
@@ -88,6 +88,7 @@ public class LogicalOrToUnionRule extends
RelRule<LogicalOrToUnionRule.Config> {
relBldr.push(IgniteLogicalTableScan.create(
scan.getCluster(),
trait,
+ scan.getHints(),
scan.getTable(),
scan.projects(),
condition,
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ProjectScanMergeRule.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ProjectScanMergeRule.java
index 3b925468da..081d9280fa 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ProjectScanMergeRule.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ProjectScanMergeRule.java
@@ -170,6 +170,7 @@ public abstract class ProjectScanMergeRule<T extends
ProjectableFilterableTableS
return IgniteLogicalTableScan.create(
cluster,
traits,
+ scan.getHints(),
scan.getTable(),
projections,
cond,
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTable.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTable.java
index 77de799b7d..378076462f 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTable.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTable.java
@@ -24,6 +24,7 @@ import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.hint.RelHint;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.schema.Schema;
@@ -78,7 +79,7 @@ public interface IgniteTable extends TranslatableTable,
Wrapper {
/** {@inheritDoc} */
@Override
default TableScan toRel(RelOptTable.ToRelContext context, RelOptTable
relOptTable) {
- return toRel(context.getCluster(), relOptTable);
+ return toRel(context.getCluster(), relOptTable,
context.getTableHints());
}
/**
@@ -86,9 +87,10 @@ public interface IgniteTable extends TranslatableTable,
Wrapper {
*
* @param cluster Custer.
* @param relOptTbl Table.
+ * @param hints Hints.
* @return Table relational expression.
*/
- TableScan toRel(RelOptCluster cluster, RelOptTable relOptTbl);
+ TableScan toRel(RelOptCluster cluster, RelOptTable relOptTbl,
List<RelHint> hints);
/**
* Returns table distribution.
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java
index 69dbebaa30..ace5b069e3 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java
@@ -36,6 +36,7 @@ import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelReferentialConstraint;
import org.apache.calcite.rel.core.TableModify;
+import org.apache.calcite.rel.hint.RelHint;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rex.RexNode;
@@ -173,6 +174,7 @@ public class IgniteTableImpl extends AbstractTable
implements InternalIgniteTabl
public IgniteLogicalTableScan toRel(
RelOptCluster cluster,
RelOptTable relOptTbl,
+ List<RelHint> hints,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
@Nullable ImmutableBitSet requiredColumns
@@ -180,7 +182,7 @@ public class IgniteTableImpl extends AbstractTable
implements InternalIgniteTabl
RelTraitSet traitSet = cluster.traitSetOf(distribution())
.replace(RewindabilityTrait.REWINDABLE);
- return IgniteLogicalTableScan.create(cluster, traitSet, relOptTbl,
proj, cond, requiredColumns);
+ return IgniteLogicalTableScan.create(cluster, traitSet, hints,
relOptTbl, proj, cond, requiredColumns);
}
/** {@inheritDoc} */
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/InternalIgniteTable.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/InternalIgniteTable.java
index 1b88673e94..66236c19aa 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/InternalIgniteTable.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/InternalIgniteTable.java
@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.rel.core.TableModify;
+import org.apache.calcite.rel.hint.RelHint;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.ignite.internal.schema.BinaryRow;
@@ -40,8 +41,8 @@ import org.jetbrains.annotations.Nullable;
public interface InternalIgniteTable extends IgniteTable {
/** {@inheritDoc} */
@Override
- default IgniteLogicalTableScan toRel(RelOptCluster cluster, RelOptTable
relOptTbl) {
- return toRel(cluster, relOptTbl, null, null, null);
+ default IgniteLogicalTableScan toRel(RelOptCluster cluster, RelOptTable
relOptTbl, List<RelHint> hints) {
+ return toRel(cluster, relOptTbl, hints, null, null, null);
}
/**
@@ -62,6 +63,7 @@ public interface InternalIgniteTable extends IgniteTable {
IgniteLogicalTableScan toRel(
RelOptCluster cluster,
RelOptTable relOptTbl,
+ List<RelHint> hints,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
@Nullable ImmutableBitSet requiredColumns
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
index e05d425d5e..cd4f3a3625 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
@@ -29,6 +29,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
@@ -57,6 +58,9 @@ import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelReferentialConstraint;
import org.apache.calcite.rel.RelVisitor;
import org.apache.calcite.rel.core.TableModify.Operation;
+import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.hint.HintStrategyTable;
+import org.apache.calcite.rel.hint.RelHint;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeField;
@@ -73,6 +77,7 @@ import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.sql.SqlFunction;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql2rel.InitializerContext;
+import org.apache.calcite.sql2rel.SqlToRelConverter;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.Util;
import org.apache.ignite.internal.index.ColumnCollation;
@@ -223,12 +228,17 @@ public abstract class AbstractPlannerTest extends
IgniteAbstractTest {
* Create planner context for specified query.
*/
protected PlanningContext plannerCtx(String sql, IgniteSchema
publicSchema, String... disabledRules) {
- return plannerCtx(sql, Collections.singleton(publicSchema),
disabledRules);
+ return plannerCtx(sql, Collections.singleton(publicSchema), null,
disabledRules);
}
- protected PlanningContext plannerCtx(String sql, Collection<IgniteSchema>
schemas, String... disabledRules) {
+ protected PlanningContext plannerCtx(
+ String sql,
+ Collection<IgniteSchema> schemas,
+ HintStrategyTable hintStrategies,
+ String... disabledRules
+ ) {
PlanningContext ctx = PlanningContext.builder()
- .parentContext(baseQueryContext(schemas))
+ .parentContext(baseQueryContext(schemas, hintStrategies))
.query(sql)
.build();
@@ -241,7 +251,7 @@ public abstract class AbstractPlannerTest extends
IgniteAbstractTest {
return ctx;
}
- protected BaseQueryContext baseQueryContext(Collection<IgniteSchema>
schemas) {
+ protected BaseQueryContext baseQueryContext(Collection<IgniteSchema>
schemas, @Nullable HintStrategyTable hintStrategies) {
SchemaPlus rootSchema = createRootSchema(false);
SchemaPlus dfltSchema = null;
@@ -253,10 +263,17 @@ public abstract class AbstractPlannerTest extends
IgniteAbstractTest {
}
}
+ SqlToRelConverter.Config relConvCfg =
FRAMEWORK_CONFIG.getSqlToRelConverterConfig();
+
+ if (hintStrategies != null) {
+ relConvCfg = relConvCfg.withHintStrategyTable(hintStrategies);
+ }
+
return BaseQueryContext.builder()
.frameworkConfig(
newConfigBuilder(FRAMEWORK_CONFIG)
.defaultSchema(dfltSchema)
+ .sqlToRelConverterConfig(relConvCfg)
.build()
)
.logger(log)
@@ -297,11 +314,16 @@ public abstract class AbstractPlannerTest extends
IgniteAbstractTest {
* Optimize the specified query and build query physical plan for a test.
*/
protected IgniteRel physicalPlan(String sql, IgniteSchema publicSchema,
String... disabledRules) throws Exception {
- return physicalPlan(sql, plannerCtx(sql, publicSchema, disabledRules));
+ return physicalPlan(sql, Collections.singleton(publicSchema), null,
disabledRules);
}
- protected IgniteRel physicalPlan(String sql, Collection<IgniteSchema>
schemas, String... disabledRules) throws Exception {
- return physicalPlan(plannerCtx(sql, schemas, disabledRules));
+ protected IgniteRel physicalPlan(
+ String sql,
+ Collection<IgniteSchema> schemas,
+ HintStrategyTable hintStrategies,
+ String... disabledRules
+ ) throws Exception {
+ return physicalPlan(plannerCtx(sql, schemas, hintStrategies,
disabledRules));
}
protected IgniteRel physicalPlan(PlanningContext ctx) throws Exception {
@@ -471,7 +493,17 @@ public abstract class AbstractPlannerTest extends
IgniteAbstractTest {
Predicate<T> predicate,
String... disabledRules
) throws Exception {
- IgniteRel plan = physicalPlan(sql, schemas, disabledRules);
+ assertPlan(sql, schemas, predicate, null, disabledRules);
+ }
+
+ protected <T extends RelNode> void assertPlan(
+ String sql,
+ Collection<IgniteSchema> schemas,
+ Predicate<T> predicate,
+ HintStrategyTable hintStrategies,
+ String... disabledRules
+ ) throws Exception {
+ IgniteRel plan = physicalPlan(sql, schemas, hintStrategies,
disabledRules);
checkSplitAndSerialization(plan, schemas);
@@ -650,6 +682,9 @@ public abstract class AbstractPlannerTest extends
IgniteAbstractTest {
clearTraits(expected);
clearTraits(deserialized);
+ // Hints are not serializable.
+ clearHints(expected);
+
if (!expected.deepEquals(deserialized)) {
assertTrue(
expected.deepEquals(deserialized),
@@ -690,6 +725,14 @@ public abstract class AbstractPlannerTest extends
IgniteAbstractTest {
rel.getInputs().forEach(this::clearTraits);
}
+ protected void clearHints(RelNode rel) {
+ if (rel instanceof TableScan) {
+ IgniteTestUtils.setFieldValue(rel, TableScan.class, "hints",
ImmutableList.of());
+ }
+
+ rel.getInputs().forEach(this::clearHints);
+ }
+
/** Test table. */
public abstract static class TestTable implements InternalIgniteTable {
private final String name;
@@ -745,11 +788,12 @@ public abstract class AbstractPlannerTest extends
IgniteAbstractTest {
public IgniteLogicalTableScan toRel(
RelOptCluster cluster,
RelOptTable relOptTbl,
+ List<RelHint> hints,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
@Nullable ImmutableBitSet requiredColumns
) {
- return IgniteLogicalTableScan.create(cluster, cluster.traitSet(),
relOptTbl, proj, cond, requiredColumns);
+ return IgniteLogicalTableScan.create(cluster, cluster.traitSet(),
hints, relOptTbl, proj, cond, requiredColumns);
}
/** {@inheritDoc} */
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTest.java
index 09b28b89ba..ad8ad61353 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTest.java
@@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
@@ -35,10 +36,13 @@ import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.RelVisitor;
+import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.hint.HintStrategyTable;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.util.ImmutableIntList;
+import org.apache.calcite.util.Util;
import org.apache.ignite.internal.sql.engine.metadata.ColocationGroup;
import org.apache.ignite.internal.sql.engine.metadata.cost.IgniteCostFactory;
import org.apache.ignite.internal.sql.engine.prepare.IgnitePlanner;
@@ -860,6 +864,34 @@ public class PlannerTest extends AbstractPlannerTest {
assertPlan(sql, publicSchema, (k) -> true);
}
+ @Test
+ public void checkTableHintsHandling() throws Exception {
+ IgniteSchema publicSchema = createSchema(
+ createTable("PERSON", IgniteDistributions.affinity(0,
"ignored", "ignored"),
+ "PK", Integer.class, "ORG_ID", Integer.class
+ ),
+ createTable("COMPANY", IgniteDistributions.affinity(0,
"ignored", "ignored"),
+ "PK", Integer.class, "ID", Integer.class
+ )
+ );
+
+ String sql = "SELECT * FROM person /*+ use_index(ORG_ID), extra */ t1
JOIN company /*+ use_index(ID) */ t2 ON t1.org_id = t2.id";
+
+ HintStrategyTable hintStrategies = HintStrategyTable.builder()
+ .hintStrategy("use_index", (hint, rel) -> true)
+ .hintStrategy("extra", (hint, rel) -> true)
+ .build();
+
+ Predicate<RelNode> hintCheck =
nodeOrAnyChild(isInstanceOf(TableScan.class)
+ .and(t ->
"PERSON".equals(Util.last(t.getTable().getQualifiedName())))
+ .and(t -> t.getHints().size() == 2)
+ ).and(nodeOrAnyChild(isInstanceOf(TableScan.class)
+ .and(t ->
"COMPANY".equals(Util.last(t.getTable().getQualifiedName())))
+ .and(t -> t.getHints().size() == 1)));
+
+ assertPlan(sql, Collections.singleton(publicSchema), hintCheck,
hintStrategies);
+ }
+
/**
* IntermediateMapping.
* TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859