blob: a3cd8b3408c50c3f72e5e4d94eb66e5d7847da70 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.sql.engine.prepare;
import static org.apache.ignite.internal.sql.engine.prepare.IgnitePrograms.cbo;
import static org.apache.ignite.internal.sql.engine.prepare.IgnitePrograms.hep;
import java.util.ArrayList;
import java.util.List;
import org.apache.calcite.plan.RelOptRule;
import org.apache.calcite.plan.RelRule;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.logical.LogicalAggregate;
import org.apache.calcite.rel.logical.LogicalFilter;
import org.apache.calcite.rel.logical.LogicalJoin;
import org.apache.calcite.rel.logical.LogicalProject;
import org.apache.calcite.rel.logical.LogicalSort;
import org.apache.calcite.rel.rules.AggregateMergeRule;
import org.apache.calcite.rel.rules.CoreRules;
import org.apache.calcite.rel.rules.FilterJoinRule.FilterIntoJoinRule;
import org.apache.calcite.rel.rules.FilterMergeRule;
import org.apache.calcite.rel.rules.FilterProjectTransposeRule;
import org.apache.calcite.rel.rules.JoinPushExpressionsRule;
import org.apache.calcite.rel.rules.JoinPushThroughJoinRule;
import org.apache.calcite.rel.rules.ProjectFilterTransposeRule;
import org.apache.calcite.rel.rules.ProjectMergeRule;
import org.apache.calcite.rel.rules.ProjectRemoveRule;
import org.apache.calcite.rel.rules.PruneEmptyRules;
import org.apache.calcite.rel.rules.SortRemoveRule;
import org.apache.calcite.tools.Program;
import org.apache.calcite.tools.RuleSet;
import org.apache.calcite.tools.RuleSets;
import org.apache.ignite.internal.sql.engine.rule.CorrelateToNestedLoopRule;
import org.apache.ignite.internal.sql.engine.rule.FilterConverterRule;
import org.apache.ignite.internal.sql.engine.rule.FilterSpoolMergeToHashIndexSpoolRule;
import org.apache.ignite.internal.sql.engine.rule.FilterSpoolMergeToSortedIndexSpoolRule;
import org.apache.ignite.internal.sql.engine.rule.HashAggregateConverterRule;
import org.apache.ignite.internal.sql.engine.rule.LogicalScanConverterRule;
import org.apache.ignite.internal.sql.engine.rule.MergeJoinConverterRule;
import org.apache.ignite.internal.sql.engine.rule.NestedLoopJoinConverterRule;
import org.apache.ignite.internal.sql.engine.rule.ProjectConverterRule;
import org.apache.ignite.internal.sql.engine.rule.SetOpConverterRule;
import org.apache.ignite.internal.sql.engine.rule.SortAggregateConverterRule;
import org.apache.ignite.internal.sql.engine.rule.SortConverterRule;
import org.apache.ignite.internal.sql.engine.rule.SortExchangeTransposeRule;
import org.apache.ignite.internal.sql.engine.rule.TableFunctionScanConverterRule;
import org.apache.ignite.internal.sql.engine.rule.TableModifyConverterRule;
import org.apache.ignite.internal.sql.engine.rule.TableModifyToKeyValuePutRule;
import org.apache.ignite.internal.sql.engine.rule.TableScanToKeyValueGetRule;
import org.apache.ignite.internal.sql.engine.rule.UnionConverterRule;
import org.apache.ignite.internal.sql.engine.rule.ValuesConverterRule;
import org.apache.ignite.internal.sql.engine.rule.logical.ExposeIndexRule;
import org.apache.ignite.internal.sql.engine.rule.logical.FilterScanMergeRule;
import org.apache.ignite.internal.sql.engine.rule.logical.IgniteJoinConditionPushRule;
import org.apache.ignite.internal.sql.engine.rule.logical.LogicalOrToUnionRule;
import org.apache.ignite.internal.sql.engine.rule.logical.ProjectScanMergeRule;
/**
* Represents a planner phase with its description and a used rule set.
*/
public enum PlannerPhase {
HEP_SUBQUERIES_TO_CORRELATES(
"Heuristic phase to convert subqueries into correlates",
CoreRules.FILTER_SUB_QUERY_TO_CORRELATE,
CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE,
CoreRules.JOIN_SUB_QUERY_TO_CORRELATE
) {
/** {@inheritDoc} */
@Override
public Program getProgram(PlanningContext ctx) {
return hep(getRules(ctx));
}
},
HEP_TO_SIMPLE_KEY_VALUE_OPERATION(
"Heuristic phase to convert relational tree to simple Key-Value operation",
TableScanToKeyValueGetRule.INSTANCE,
TableModifyToKeyValuePutRule.PROJECT,
TableModifyToKeyValuePutRule.VALUES
) {
/** {@inheritDoc} */
@Override
public Program getProgram(PlanningContext ctx) {
return hep(getRules(ctx));
}
},
HEP_FILTER_PUSH_DOWN(
"Heuristic phase to push down filters",
FilterScanMergeRule.TABLE_SCAN_SKIP_CORRELATED,
FilterScanMergeRule.SYSTEM_VIEW_SCAN_SKIP_CORRELATED,
CoreRules.FILTER_MERGE,
CoreRules.FILTER_AGGREGATE_TRANSPOSE,
CoreRules.FILTER_SET_OP_TRANSPOSE,
IgniteJoinConditionPushRule.INSTANCE,
CoreRules.FILTER_CORRELATE,
CoreRules.FILTER_INTO_JOIN,
CoreRules.FILTER_PROJECT_TRANSPOSE
) {
/** {@inheritDoc} */
@Override
public Program getProgram(PlanningContext ctx) {
return hep(getRules(ctx));
}
},
HEP_PROJECT_PUSH_DOWN(
"Heuristic phase to push down and merge projects",
ProjectScanMergeRule.TABLE_SCAN_SKIP_CORRELATED,
ProjectScanMergeRule.SYSTEM_VIEW_SCAN_SKIP_CORRELATED,
CoreRules.JOIN_PUSH_EXPRESSIONS,
CoreRules.PROJECT_MERGE,
CoreRules.PROJECT_REMOVE,
CoreRules.PROJECT_FILTER_TRANSPOSE
) {
/** {@inheritDoc} */
@Override
public Program getProgram(PlanningContext ctx) {
return hep(getRules(ctx));
}
},
OPTIMIZATION(
"Main optimization phase",
FilterMergeRule.Config.DEFAULT
.withOperandFor(LogicalFilter.class).toRule(),
JoinPushThroughJoinRule.Config.RIGHT
.withOperandFor(LogicalJoin.class).toRule(),
JoinPushExpressionsRule.Config.DEFAULT
.withOperandFor(LogicalJoin.class).toRule(),
IgniteJoinConditionPushRule.INSTANCE,
FilterIntoJoinRule.FilterIntoJoinRuleConfig.DEFAULT
.withOperandSupplier(b0 ->
b0.operand(LogicalFilter.class).oneInput(b1 ->
b1.operand(LogicalJoin.class).anyInputs())).toRule(),
FilterProjectTransposeRule.Config.DEFAULT
.withOperandFor(LogicalFilter.class, f -> true, LogicalProject.class, p -> true)
.toRule(),
ProjectFilterTransposeRule.Config.DEFAULT
.withOperandFor(LogicalProject.class, LogicalFilter.class).toRule(),
ProjectMergeRule.Config.DEFAULT
.withOperandFor(LogicalProject.class).toRule(),
ProjectRemoveRule.Config.DEFAULT
.withOperandSupplier(b ->
b.operand(LogicalProject.class)
.predicate(ProjectRemoveRule::isTrivial)
.anyInputs()).toRule(),
AggregateMergeRule.Config.DEFAULT
.withOperandSupplier(b0 ->
b0.operand(LogicalAggregate.class)
.oneInput(b1 ->
b1.operand(LogicalAggregate.class)
.predicate(Aggregate::isSimple)
.anyInputs())).toRule(),
CoreRules.AGGREGATE_EXPAND_DISTINCT_AGGREGATES_TO_JOIN,
SortRemoveRule.Config.DEFAULT
.withOperandSupplier(b ->
b.operand(LogicalSort.class)
.anyInputs()).toRule(),
SortExchangeTransposeRule.INSTANCE,
CoreRules.UNION_MERGE,
CoreRules.MINUS_MERGE,
CoreRules.INTERSECT_MERGE,
CoreRules.UNION_REMOVE,
CoreRules.JOIN_COMMUTE,
CoreRules.AGGREGATE_REMOVE,
CoreRules.JOIN_COMMUTE_OUTER,
PruneEmptyRules.CORRELATE_LEFT_INSTANCE,
PruneEmptyRules.CORRELATE_RIGHT_INSTANCE,
// Useful of this rule is not clear now.
// CoreRules.AGGREGATE_REDUCE_FUNCTIONS,
((RelRule<?>) PruneEmptyRules.SORT_FETCH_ZERO_INSTANCE).config
.withOperandSupplier(b ->
b.operand(LogicalSort.class).anyInputs())
.toRule(),
ExposeIndexRule.INSTANCE,
ProjectScanMergeRule.TABLE_SCAN,
ProjectScanMergeRule.INDEX_SCAN,
ProjectScanMergeRule.SYSTEM_VIEW_SCAN,
FilterSpoolMergeToSortedIndexSpoolRule.INSTANCE,
FilterSpoolMergeToHashIndexSpoolRule.INSTANCE,
FilterScanMergeRule.TABLE_SCAN,
FilterScanMergeRule.INDEX_SCAN,
FilterScanMergeRule.SYSTEM_VIEW_SCAN,
LogicalOrToUnionRule.INSTANCE,
// TODO: https://issues.apache.org/jira/browse/IGNITE-16334 join rules ordering is significant here.
MergeJoinConverterRule.INSTANCE,
// TODO: https://issues.apache.org/jira/browse/IGNITE-21286
// CorrelatedNestedLoopJoinRule.INSTANCE,
CorrelateToNestedLoopRule.INSTANCE,
NestedLoopJoinConverterRule.INSTANCE,
ValuesConverterRule.INSTANCE,
LogicalScanConverterRule.INDEX_SCAN,
LogicalScanConverterRule.TABLE_SCAN,
LogicalScanConverterRule.SYSTEM_VIEW_SCAN,
HashAggregateConverterRule.COLOCATED,
HashAggregateConverterRule.MAP_REDUCE,
SortAggregateConverterRule.COLOCATED,
SortAggregateConverterRule.MAP_REDUCE,
SetOpConverterRule.COLOCATED_MINUS,
SetOpConverterRule.MAP_REDUCE_MINUS,
SetOpConverterRule.COLOCATED_INTERSECT,
SetOpConverterRule.MAP_REDUCE_INTERSECT,
ProjectConverterRule.INSTANCE,
FilterConverterRule.INSTANCE,
TableModifyConverterRule.INSTANCE,
UnionConverterRule.INSTANCE,
SortConverterRule.INSTANCE,
TableFunctionScanConverterRule.INSTANCE
) {
/** {@inheritDoc} */
@Override
public Program getProgram(PlanningContext ctx) {
return cbo(getRules(ctx));
}
};
public final String description;
private final List<RelOptRule> rules;
/**
* Constructor.
*
* @param description A description of the phase.
* @param rules A list of rules associated with the current phase.
*/
PlannerPhase(String description, RelOptRule... rules) {
this.description = description;
this.rules = List.of(rules);
}
/**
* Returns rule set, calculated on the basis of query, planner context and planner phase.
*
* @param ctx Planner context.
* @return Rule set.
*/
public RuleSet getRules(PlanningContext ctx) {
List<RelOptRule> rules = new ArrayList<>(this.rules);
return ctx.rules(RuleSets.ofList(rules));
}
/**
* Returns a program, calculated on the basis of query, planner context planner phase and rules set.
*
* @param ctx Planner context.
* @return Rule set.
*/
public abstract Program getProgram(PlanningContext ctx);
}