blob: 49b6d3804e0e5ca71ef5fdf95b6e750fab524264 [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.drill.exec.planner;
import org.apache.drill.exec.planner.logical.ConvertMetadataAggregateToDirectScanRule;
import org.apache.drill.exec.planner.physical.MetadataAggPrule;
import org.apache.drill.exec.planner.physical.MetadataControllerPrule;
import org.apache.drill.exec.planner.physical.MetadataHandlerPrule;
import org.apache.drill.shaded.guava.com.google.common.collect.ImmutableSet;
import org.apache.drill.shaded.guava.com.google.common.collect.ImmutableSet.Builder;
import org.apache.drill.shaded.guava.com.google.common.collect.Lists;
import org.apache.calcite.plan.RelOptRule;
import org.apache.calcite.rel.core.RelFactories;
import org.apache.calcite.rel.rules.JoinToMultiJoinRule;
import org.apache.calcite.rel.rules.LoptOptimizeJoinRule;
import org.apache.calcite.tools.RuleSet;
import org.apache.calcite.tools.RuleSets;
import org.apache.drill.exec.ops.OptimizerRulesContext;
import org.apache.drill.exec.planner.index.rules.DbScanSortRemovalRule;
import org.apache.drill.exec.planner.index.rules.DbScanToIndexScanPrule;
import org.apache.drill.exec.planner.logical.DrillAggregateRule;
import org.apache.drill.exec.planner.logical.DrillCorrelateRule;
import org.apache.drill.exec.planner.logical.DrillFilterAggregateTransposeRule;
import org.apache.drill.exec.planner.logical.DrillFilterItemStarReWriterRule;
import org.apache.drill.exec.planner.logical.DrillFilterJoinRules;
import org.apache.drill.exec.planner.logical.DrillFilterRule;
import org.apache.drill.exec.planner.logical.DrillJoinRel;
import org.apache.drill.exec.planner.logical.DrillJoinRule;
import org.apache.drill.exec.planner.logical.DrillLimitRule;
import org.apache.drill.exec.planner.logical.DrillMergeProjectRule;
import org.apache.drill.exec.planner.logical.DrillProjectLateralJoinTransposeRule;
import org.apache.drill.exec.planner.logical.DrillProjectPushIntoLateralJoinRule;
import org.apache.drill.exec.planner.logical.DrillProjectRule;
import org.apache.drill.exec.planner.logical.DrillPushFilterPastProjectRule;
import org.apache.drill.exec.planner.logical.DrillPushLimitToScanRule;
import org.apache.drill.exec.planner.logical.DrillPushProjectIntoScanRule;
import org.apache.drill.exec.planner.logical.DrillPushProjectPastFilterRule;
import org.apache.drill.exec.planner.logical.DrillPushProjectPastJoinRule;
import org.apache.drill.exec.planner.logical.DrillPushRowKeyJoinToScanRule;
import org.apache.drill.exec.planner.logical.DrillReduceAggregatesRule;
import org.apache.drill.exec.planner.logical.DrillReduceExpressionsRule;
import org.apache.drill.exec.planner.logical.DrillRelFactories;
import org.apache.drill.exec.planner.logical.DrillScanRule;
import org.apache.drill.exec.planner.logical.DrillSortRule;
import org.apache.drill.exec.planner.logical.DrillUnionAllRule;
import org.apache.drill.exec.planner.logical.DrillUnnestRule;
import org.apache.drill.exec.planner.logical.DrillValuesRule;
import org.apache.drill.exec.planner.logical.DrillWindowRule;
import org.apache.drill.exec.planner.logical.partition.ParquetPruneScanRule;
import org.apache.drill.exec.planner.logical.partition.PruneScanRule;
import org.apache.drill.exec.planner.logical.ConvertCountToDirectScanRule;
import org.apache.drill.exec.planner.physical.AnalyzePrule;
import org.apache.drill.exec.planner.physical.ConvertCountToDirectScanPrule;
import org.apache.drill.exec.planner.physical.LateralJoinPrule;
import org.apache.drill.exec.planner.physical.DirectScanPrule;
import org.apache.drill.exec.planner.physical.FilterPrule;
import org.apache.drill.exec.planner.physical.HashAggPrule;
import org.apache.drill.exec.planner.physical.HashJoinPrule;
import org.apache.drill.exec.planner.physical.LimitPrule;
import org.apache.drill.exec.planner.physical.LimitExchangeTransposeRule;
import org.apache.drill.exec.planner.physical.MergeJoinPrule;
import org.apache.drill.exec.planner.physical.NestedLoopJoinPrule;
import org.apache.drill.exec.planner.physical.PlannerSettings;
import org.apache.drill.exec.planner.physical.ProjectPrule;
import org.apache.drill.exec.planner.physical.PushLimitToTopN;
import org.apache.drill.exec.planner.physical.RowKeyJoinPrule;
import org.apache.drill.exec.planner.physical.ScanPrule;
import org.apache.drill.exec.planner.physical.ScreenPrule;
import org.apache.drill.exec.planner.physical.SortConvertPrule;
import org.apache.drill.exec.planner.physical.SortPrule;
import org.apache.drill.exec.planner.physical.StreamAggPrule;
import org.apache.drill.exec.planner.physical.UnionAllPrule;
import org.apache.drill.exec.planner.physical.UnnestPrule;
import org.apache.drill.exec.planner.physical.ValuesPrule;
import org.apache.drill.exec.planner.physical.WindowPrule;
import org.apache.drill.exec.planner.physical.WriterPrule;
import org.apache.drill.exec.store.AbstractStoragePlugin;
import org.apache.drill.exec.store.StoragePlugin;
import org.apache.drill.exec.store.parquet.ParquetPushDownFilter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Returns RuleSet for concrete planner phase.
* Only rules which use DrillRelFactories should be used in this enum.
*/
public enum PlannerPhase {
LOGICAL_PRUNE_AND_JOIN("Logical Planning (with join and partition pruning)") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.mergedRuleSets(
getDrillBasicRules(context),
getPruneScanRules(context),
getJoinPermRules(context),
getDrillUserConfigurableLogicalRules(context),
getStorageRules(context, plugins, this));
}
},
WINDOW_REWRITE("Window Function rewrites") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return RuleSets.ofList(
RuleInstance.CALC_INSTANCE,
RuleInstance.PROJECT_TO_LOGICAL_PROJECT_AND_WINDOW_RULE
);
}
},
SUBQUERY_REWRITE("Sub-queries rewrites") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return RuleSets.ofList(
RuleInstance.SUB_QUERY_FILTER_REMOVE_RULE,
RuleInstance.SUB_QUERY_PROJECT_REMOVE_RULE,
RuleInstance.SUB_QUERY_JOIN_REMOVE_RULE
);
}
},
LOGICAL_PRUNE("Logical Planning (with partition pruning)") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.mergedRuleSets(
getDrillBasicRules(context),
getPruneScanRules(context),
getDrillUserConfigurableLogicalRules(context),
getStorageRules(context, plugins, this));
}
},
JOIN_PLANNING("LOPT Join Planning") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
List<RelOptRule> rules = Lists.newArrayList();
if (context.getPlannerSettings().isJoinOptimizationEnabled()) {
rules.add(DRILL_JOIN_TO_MULTIJOIN_RULE);
rules.add(DRILL_LOPT_OPTIMIZE_JOIN_RULE);
}
rules.add(RuleInstance.PROJECT_REMOVE_RULE);
return PlannerPhase.mergedRuleSets(
RuleSets.ofList(rules),
getStorageRules(context, plugins, this)
);
}
},
ROWKEYJOIN_CONVERSION("Convert Join to RowKeyJoin") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
List<RelOptRule> rules = Lists.newArrayList();
if (context.getPlannerSettings().isRowKeyJoinConversionEnabled()) {
rules.add(DrillPushRowKeyJoinToScanRule.JOIN);
}
return PlannerPhase.mergedRuleSets(
RuleSets.ofList(rules),
getStorageRules(context, plugins, this)
);
}
},
SUM_CONVERSION("Convert SUM to $SUM0") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.mergedRuleSets(
RuleSets.ofList(
DrillReduceAggregatesRule.INSTANCE_SUM,
DrillReduceAggregatesRule.INSTANCE_WINDOW_SUM),
getStorageRules(context, plugins, this)
);
}
},
PARTITION_PRUNING("Partition Prune Planning") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.mergedRuleSets(getPruneScanRules(context), getStorageRules(context, plugins, this));
}
},
PHYSICAL_PARTITION_PRUNING("Physical Partition Prune Planning") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.mergedRuleSets(getPhysicalPruneScanRules(context), getStorageRules(context, plugins, this));
}
},
DIRECTORY_PRUNING("Directory Prune Planning") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.mergedRuleSets(getDirPruneScanRules(context), getStorageRules(context, plugins, this));
}
},
LOGICAL("Logical Planning (no pruning or join).") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.mergedRuleSets(
PlannerPhase.getDrillBasicRules(context),
PlannerPhase.getDrillUserConfigurableLogicalRules(context),
getStorageRules(context, plugins, this));
}
},
PHYSICAL("Physical Planning") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.mergedRuleSets(
PlannerPhase.getPhysicalRules(context),
getIndexRules(context),
getStorageRules(context, plugins, this));
}
},
PRE_LOGICAL_PLANNING("Planning with Hep planner only for rules, which are failed for Volcano planner") {
public RuleSet getRules (OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return PlannerPhase.getSetOpTransposeRules();
}
},
TRANSITIVE_CLOSURE("Transitive closure") {
public RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins) {
return getJoinTransitiveClosureRules();
}
};
public final String description;
PlannerPhase(String description) {
this.description = description;
}
public abstract RuleSet getRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins);
private static RuleSet getStorageRules(OptimizerRulesContext context, Collection<StoragePlugin> plugins,
PlannerPhase phase) {
final Builder<RelOptRule> rules = ImmutableSet.builder();
for(StoragePlugin plugin : plugins){
if(plugin instanceof AbstractStoragePlugin){
rules.addAll(((AbstractStoragePlugin) plugin).getOptimizerRules(context, phase));
}else{
rules.addAll(plugin.getOptimizerRules(context));
}
}
return RuleSets.ofList(rules.build());
}
static final RelOptRule DRILL_JOIN_TO_MULTIJOIN_RULE =
new JoinToMultiJoinRule(DrillJoinRel.class, DrillRelFactories.LOGICAL_BUILDER);
static final RelOptRule DRILL_LOPT_OPTIMIZE_JOIN_RULE =
new LoptOptimizeJoinRule(DrillRelBuilder.proto(
DrillRelFactories.DRILL_LOGICAL_JOIN_FACTORY,
DrillRelFactories.DRILL_LOGICAL_PROJECT_FACTORY,
DrillRelFactories.DRILL_LOGICAL_FILTER_FACTORY));
/**
* Get a list of logical rules that can be turned on or off by session/system options.
*
* If a rule is intended to always be included with the logical set, it should be added
* to the immutable list created in the getDrillBasicRules() method below.
*
* @param optimizerRulesContext - used to get the list of planner settings, other rules may
* also in the future need to get other query state from this,
* such as the available list of UDFs (as is used by the
* DrillMergeProjectRule created in getDrillBasicRules())
* @return - a list of rules that have been filtered to leave out
* rules that have been turned off by system or session settings
*/
static RuleSet getDrillUserConfigurableLogicalRules(OptimizerRulesContext optimizerRulesContext) {
final PlannerSettings ps = optimizerRulesContext.getPlannerSettings();
// This list is used to store rules that can be turned on an off
// by user facing planning options
final Builder<RelOptRule> userConfigurableRules = ImmutableSet.builder();
if (ps.isConstantFoldingEnabled()) {
// TODO - DRILL-2218
userConfigurableRules.add(RuleInstance.PROJECT_INSTANCE);
userConfigurableRules.add(DrillReduceExpressionsRule.FILTER_INSTANCE_DRILL);
userConfigurableRules.add(DrillReduceExpressionsRule.CALC_INSTANCE_DRILL);
}
return RuleSets.ofList(userConfigurableRules.build());
}
/*
* These basic rules don't require any context, so singleton instances can be used.
* These are merged with per-query rules in getDrillBasicRules() below.
*/
final static ImmutableSet<RelOptRule> staticRuleSet = ImmutableSet.<RelOptRule> builder().add(
// Add support for Distinct Union (by using Union-All followed by Distinct)
RuleInstance.UNION_TO_DISTINCT_RULE,
// Add support for WHERE style joins.
DrillFilterJoinRules.FILTER_INTO_JOIN,
DrillFilterJoinRules.JOIN_PUSH_CONDITION,
RuleInstance.JOIN_PUSH_EXPRESSIONS_RULE,
// End support for WHERE style joins.
/*
Filter push-down related rules
*/
DrillPushFilterPastProjectRule.INSTANCE,
// Due to infinite loop in planning (DRILL-3257/CALCITE-1271), temporarily use this rule in Hep planner
// RuleInstance.FILTER_SET_OP_TRANSPOSE_RULE,
DrillFilterAggregateTransposeRule.INSTANCE,
DrillProjectLateralJoinTransposeRule.INSTANCE,
DrillProjectPushIntoLateralJoinRule.INSTANCE,
RuleInstance.FILTER_MERGE_RULE,
RuleInstance.FILTER_CORRELATE_RULE,
RuleInstance.AGGREGATE_REMOVE_RULE,
RuleInstance.PROJECT_REMOVE_RULE,
RuleInstance.SORT_REMOVE_RULE,
RuleInstance.AGGREGATE_EXPAND_DISTINCT_AGGREGATES_RULE,
DrillReduceAggregatesRule.INSTANCE,
/*
Projection push-down related rules
*/
DrillPushProjectPastFilterRule.INSTANCE,
DrillPushProjectPastJoinRule.INSTANCE,
// Due to infinite loop in planning (DRILL-3257/CALCITE-1271), temporarily use this rule in Hep planner
// RuleInstance.PROJECT_SET_OP_TRANSPOSE_RULE,
RuleInstance.PROJECT_WINDOW_TRANSPOSE_RULE,
DrillPushProjectIntoScanRule.INSTANCE,
DrillPushProjectIntoScanRule.DRILL_LOGICAL_INSTANCE,
/*
Convert from Calcite Logical to Drill Logical Rules.
*/
RuleInstance.EXPAND_CONVERSION_RULE,
DrillScanRule.INSTANCE,
DrillFilterRule.INSTANCE,
DrillProjectRule.INSTANCE,
DrillWindowRule.INSTANCE,
DrillAggregateRule.INSTANCE,
DrillLimitRule.INSTANCE,
DrillSortRule.INSTANCE,
DrillJoinRule.INSTANCE,
DrillUnionAllRule.INSTANCE,
DrillValuesRule.INSTANCE,
DrillUnnestRule.INSTANCE,
DrillCorrelateRule.INSTANCE
).build();
/**
* Get an immutable list of rules that will always be used when running
* logical planning.
*
* This cannot be a static singleton because some of the rules need to
* reference state owned by the current query (including its allocator).
*
* If a logical rule needs to be user configurable, such as turning
* it on and off with a system/session option, add it in the
* getDrillUserConfigurableLogicalRules() method instead of here.
*
* @param optimizerRulesContext - shared state used during planning, currently used here
* to gain access to the function registry described above.
* @return - a RuleSet containing the logical rules that will always
* be used, either by VolcanoPlanner directly, or
* used VolcanoPlanner as pre-processing for LOPTPlanner.
*
* Note : Join permutation rule is excluded here.
*/
static RuleSet getDrillBasicRules(OptimizerRulesContext optimizerRulesContext) {
/*
* We have to create another copy of the ruleset with the context dependent elements;
* this cannot be reused across queries.
*/
ImmutableSet.Builder<RelOptRule> basicRules = ImmutableSet.<RelOptRule>builder()
.addAll(staticRuleSet)
.add(
DrillMergeProjectRule.getInstance(true, RelFactories.DEFAULT_PROJECT_FACTORY,
optimizerRulesContext.getFunctionRegistry())
);
if (optimizerRulesContext.getPlannerSettings().isHashJoinEnabled() &&
optimizerRulesContext.getPlannerSettings().isSemiJoinEnabled()) {
basicRules.add(RuleInstance.SEMI_JOIN_PROJECT_RULE);
}
return RuleSets.ofList(basicRules.build());
}
/**
* Get an immutable list of partition pruning rules that will be used in logical planning.
*/
static RuleSet getPruneScanRules(OptimizerRulesContext optimizerRulesContext) {
final ImmutableSet<RelOptRule> pruneRules = ImmutableSet.<RelOptRule>builder()
.addAll(getItemStarRules())
.add(
PruneScanRule.getDirFilterOnProject(optimizerRulesContext),
PruneScanRule.getDirFilterOnScan(optimizerRulesContext),
ParquetPruneScanRule.getFilterOnProjectParquet(optimizerRulesContext),
ParquetPruneScanRule.getFilterOnScanParquet(optimizerRulesContext),
// Include LIMIT_ON_PROJECT since LIMIT_ON_SCAN may not work without it
DrillPushLimitToScanRule.LIMIT_ON_PROJECT,
DrillPushLimitToScanRule.LIMIT_ON_SCAN,
PruneScanRule.getConvertAggScanToValuesRule(optimizerRulesContext)
)
.build();
return RuleSets.ofList(pruneRules);
}
/**
*
*/
static RuleSet getIndexRules(OptimizerRulesContext optimizerRulesContext) {
final PlannerSettings ps = optimizerRulesContext.getPlannerSettings();
if (!ps.isIndexPlanningEnabled()) {
return RuleSets.ofList(ImmutableSet.<RelOptRule>builder().build());
}
final ImmutableSet<RelOptRule> indexRules = ImmutableSet.<RelOptRule>builder()
.add(
DbScanToIndexScanPrule.REL_FILTER_SCAN,
DbScanToIndexScanPrule.SORT_FILTER_PROJECT_SCAN,
DbScanToIndexScanPrule.SORT_PROJECT_FILTER_PROJECT_SCAN,
DbScanToIndexScanPrule.PROJECT_FILTER_PROJECT_SCAN,
DbScanToIndexScanPrule.SORT_PROJECT_FILTER_SCAN,
DbScanToIndexScanPrule.FILTER_PROJECT_SCAN,
DbScanToIndexScanPrule.FILTER_SCAN,
DbScanSortRemovalRule.INDEX_SORT_EXCHANGE_PROJ_SCAN,
DbScanSortRemovalRule.INDEX_SORT_EXCHANGE_SCAN,
DbScanSortRemovalRule.INDEX_SORT_SCAN,
DbScanSortRemovalRule.INDEX_SORT_PROJ_SCAN
)
.build();
return RuleSets.ofList(indexRules);
}
/**
* Get an immutable list of pruning rules that will be used post physical planning.
*/
static RuleSet getPhysicalPruneScanRules(OptimizerRulesContext optimizerRulesContext) {
final ImmutableSet<RelOptRule> pruneRules = ImmutableSet.<RelOptRule>builder()
.add(
// See DRILL-4998 for more detail.
// Main reason for doing this is we want to reduce the performance regression possibility
// caused by a different join order, as a result of reduced row count in scan operator.
// Ideally this should be done in logical planning, before join order planning is done.
// Before we can make such change, we have to figure out how to adjust the selectivity
// estimation of filter operator, after filter is pushed down to scan.
ParquetPushDownFilter.getFilterOnProject(optimizerRulesContext),
ParquetPushDownFilter.getFilterOnScan(optimizerRulesContext),
DrillPushProjectIntoScanRule.DRILL_PHYSICAL_INSTANCE
)
.build();
return RuleSets.ofList(pruneRules);
}
/**
* Get an immutable list of directory-based partition pruning rules that will be used in Calcite logical planning.
*
* @param optimizerRulesContext rules context
* @return directory-based partition pruning rules
*/
static RuleSet getDirPruneScanRules(OptimizerRulesContext optimizerRulesContext) {
final Set<RelOptRule> pruneRules = ImmutableSet.<RelOptRule>builder()
.addAll(getItemStarRules())
.add(
PruneScanRule.getDirFilterOnProject(optimizerRulesContext),
PruneScanRule.getDirFilterOnScan(optimizerRulesContext),
PruneScanRule.getConvertAggScanToValuesRule(optimizerRulesContext),
ConvertCountToDirectScanRule.AGG_ON_PROJ_ON_SCAN,
ConvertCountToDirectScanRule.AGG_ON_SCAN
)
.build();
return RuleSets.ofList(pruneRules);
}
/**
* RuleSet for join permutation, used only in VolcanoPlanner.
* @param optimizerRulesContext shared state used during planning
* @return set of planning rules
*/
static RuleSet getJoinPermRules(OptimizerRulesContext optimizerRulesContext) {
return RuleSets.ofList(ImmutableSet.<RelOptRule> builder().add(
RuleInstance.JOIN_PUSH_THROUGH_JOIN_RULE_RIGHT,
RuleInstance.JOIN_PUSH_THROUGH_JOIN_RULE_LEFT
).build());
}
static final RuleSet DRILL_PHYSICAL_DISK = RuleSets.ofList(ImmutableSet.of(
ProjectPrule.INSTANCE
));
static RuleSet getPhysicalRules(OptimizerRulesContext optimizerRulesContext) {
final List<RelOptRule> ruleList = new ArrayList<>();
final PlannerSettings ps = optimizerRulesContext.getPlannerSettings();
ruleList.add(ConvertCountToDirectScanPrule.AGG_ON_PROJ_ON_SCAN);
ruleList.add(ConvertCountToDirectScanPrule.AGG_ON_SCAN);
ruleList.add(SortConvertPrule.INSTANCE);
ruleList.add(SortPrule.INSTANCE);
ruleList.add(ProjectPrule.INSTANCE);
ruleList.add(ScanPrule.INSTANCE);
ruleList.add(ScreenPrule.INSTANCE);
ruleList.add(RuleInstance.EXPAND_CONVERSION_RULE);
ruleList.add(FilterPrule.INSTANCE);
ruleList.add(LimitPrule.INSTANCE);
ruleList.add(WriterPrule.INSTANCE);
ruleList.add(WindowPrule.INSTANCE);
ruleList.add(PushLimitToTopN.INSTANCE);
ruleList.add(LimitExchangeTransposeRule.INSTANCE);
ruleList.add(UnionAllPrule.INSTANCE);
ruleList.add(ValuesPrule.INSTANCE);
ruleList.add(DirectScanPrule.INSTANCE);
ruleList.add(RowKeyJoinPrule.INSTANCE);
ruleList.add(AnalyzePrule.INSTANCE);
ruleList.add(MetadataControllerPrule.INSTANCE);
ruleList.add(MetadataHandlerPrule.INSTANCE);
ruleList.add(MetadataAggPrule.INSTANCE);
ruleList.add(ConvertMetadataAggregateToDirectScanRule.INSTANCE);
ruleList.add(UnnestPrule.INSTANCE);
ruleList.add(LateralJoinPrule.INSTANCE);
ruleList.add(DrillPushLimitToScanRule.LIMIT_ON_PROJECT);
ruleList.add(DrillPushLimitToScanRule.LIMIT_ON_SCAN);
if (ps.isHashAggEnabled()) {
ruleList.add(HashAggPrule.INSTANCE);
}
if (ps.isStreamAggEnabled()) {
ruleList.add(StreamAggPrule.INSTANCE);
}
if (ps.isHashJoinEnabled()) {
ruleList.add(HashJoinPrule.DIST_INSTANCE);
if (ps.isSemiJoinEnabled()) {
ruleList.add(HashJoinPrule.SEMI_DIST_INSTANCE);
}
if(ps.isBroadcastJoinEnabled()){
ruleList.add(HashJoinPrule.BROADCAST_INSTANCE);
if (ps.isSemiJoinEnabled()) {
ruleList.add(HashJoinPrule.SEMI_BROADCAST_INSTANCE);
}
}
}
if (ps.isMergeJoinEnabled()) {
ruleList.add(MergeJoinPrule.DIST_INSTANCE);
if(ps.isBroadcastJoinEnabled()){
ruleList.add(MergeJoinPrule.BROADCAST_INSTANCE);
}
}
// NLJ plans consist of broadcasting the right child, hence we need
// broadcast join enabled.
if (ps.isNestedLoopJoinEnabled() && ps.isBroadcastJoinEnabled()) {
ruleList.add(NestedLoopJoinPrule.INSTANCE);
}
return RuleSets.ofList(ImmutableSet.copyOf(ruleList));
}
static RuleSet create(ImmutableSet<RelOptRule> rules) {
return RuleSets.ofList(rules);
}
static RuleSet mergedRuleSets(RuleSet... ruleSets) {
final Builder<RelOptRule> relOptRuleSetBuilder = ImmutableSet.builder();
for (final RuleSet ruleSet : ruleSets) {
for (final RelOptRule relOptRule : ruleSet) {
relOptRuleSetBuilder.add(relOptRule);
}
}
return RuleSets.ofList(relOptRuleSetBuilder.build());
}
/**
* @return collection of rules to re-write item star operator for filter push down and partition pruning
*/
private static ImmutableSet<RelOptRule> getItemStarRules() {
return ImmutableSet.<RelOptRule>builder()
.add(
DrillFilterItemStarReWriterRule.PROJECT_ON_SCAN,
DrillFilterItemStarReWriterRule.FILTER_ON_SCAN,
DrillFilterItemStarReWriterRule.FILTER_PROJECT_SCAN
).build();
}
/**
* Get an immutable list of rules to transpose SetOp(Union) operator with other operators.<p>
* Note: Used by Hep planner only (failed for Volcano planner - CALCITE-1271)
*
* @return SetOp(Union) transpose rules
*/
private static RuleSet getSetOpTransposeRules() {
return RuleSets.ofList(ImmutableSet.<RelOptRule> builder()
.add(
RuleInstance.FILTER_SET_OP_TRANSPOSE_RULE,
RuleInstance.PROJECT_SET_OP_TRANSPOSE_RULE
).build());
}
/**
* RuleSet for join transitive closure, used only in HepPlanner.<p>
* TODO: {@link RuleInstance#DRILL_JOIN_PUSH_TRANSITIVE_PREDICATES_RULE} should be moved into {@link #staticRuleSet},
* (with using {@link DrillRelFactories#LOGICAL_BUILDER}) once CALCITE-1048 is solved. This block can be removed then.
*
* @return set of planning rules
*/
static RuleSet getJoinTransitiveClosureRules() {
return RuleSets.ofList(ImmutableSet.<RelOptRule> builder()
.add(
RuleInstance.DRILL_JOIN_PUSH_TRANSITIVE_PREDICATES_RULE,
DrillFilterJoinRules.DRILL_FILTER_INTO_JOIN,
RuleInstance.REMOVE_IS_NOT_DISTINCT_FROM_RULE,
DrillFilterAggregateTransposeRule.DRILL_LOGICAL_INSTANCE,
RuleInstance.DRILL_FILTER_MERGE_RULE
).build());
}
}