diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index 1bcdc5f..f794481 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -1252,6 +1252,8 @@ public void setSparkConfigUpdated(boolean isSparkConfigUpdated) { "Whether to update stale indexes automatically"), HIVEOPTPPD("hive.optimize.ppd", true, "Whether to enable predicate pushdown"), + HIVEOPTPPD_WINDOWING("hive.optimize.ppd.windowing", true, + "Whether to enable predicate pushdown through windowing"), HIVEPPDRECOGNIZETRANSITIVITY("hive.ppd.recognizetransivity", true, "Whether to transitively replicate predicate filters over equijoin conditions."), HIVEPPDREMOVEDUPLICATEFILTERS("hive.ppd.remove.duplicatefilters", true, diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveCalciteUtil.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveCalciteUtil.java index 4825a61..71dd7c6 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveCalciteUtil.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveCalciteUtil.java @@ -680,56 +680,108 @@ public Void visitCall(org.apache.calcite.rex.RexCall call) { return deterministic; } - public static boolean isDeterministicFuncOnLiterals(RexNode expr) { - boolean deterministicFuncOnLiterals = true; + private static class DeterMinisticFuncVisitorImpl extends RexVisitorImpl { + protected DeterMinisticFuncVisitorImpl() { + super(true); + } - RexVisitor visitor = new RexVisitorImpl(true) { - @Override - public Void visitCall(org.apache.calcite.rex.RexCall call) { - if (!call.getOperator().isDeterministic()) { - throw new Util.FoundOne(call); - } - return super.visitCall(call); + @Override + public Void visitCall(org.apache.calcite.rex.RexCall call) { + if (!call.getOperator().isDeterministic()) { + throw new Util.FoundOne(call); } + return super.visitCall(call); + } + + @Override + public Void visitCorrelVariable(RexCorrelVariable correlVariable) { + throw new Util.FoundOne(correlVariable); + } + + @Override + public Void visitLocalRef(RexLocalRef localRef) { + throw new Util.FoundOne(localRef); + } + + @Override + public Void visitOver(RexOver over) { + throw new Util.FoundOne(over); + } + + @Override + public Void visitDynamicParam(RexDynamicParam dynamicParam) { + throw new Util.FoundOne(dynamicParam); + } + + @Override + public Void visitRangeRef(RexRangeRef rangeRef) { + throw new Util.FoundOne(rangeRef); + } + + @Override + public Void visitFieldAccess(RexFieldAccess fieldAccess) { + throw new Util.FoundOne(fieldAccess); + } + } + + public static boolean isDeterministicFuncOnLiterals(RexNode expr) { + boolean deterministicFuncOnLiterals = true; + RexVisitor visitor = new DeterMinisticFuncVisitorImpl() { @Override public Void visitInputRef(RexInputRef inputRef) { throw new Util.FoundOne(inputRef); } + }; - @Override - public Void visitLocalRef(RexLocalRef localRef) { - throw new Util.FoundOne(localRef); - } + try { + expr.accept(visitor); + } catch (Util.FoundOne e) { + deterministicFuncOnLiterals = false; + } - @Override - public Void visitOver(RexOver over) { - throw new Util.FoundOne(over); - } + return deterministicFuncOnLiterals; + } - @Override - public Void visitDynamicParam(RexDynamicParam dynamicParam) { - throw new Util.FoundOne(dynamicParam); + public List getDeterministicFuncWithSingleInputRef(List exprs, + final Set validInputRefs) { + List determExprsWithSingleRef = new ArrayList(); + for (RexNode e : exprs) { + if (isDeterministicFuncWithSingleInputRef(e, validInputRefs)) { + determExprsWithSingleRef.add(e); } + } + return determExprsWithSingleRef; + } - @Override - public Void visitRangeRef(RexRangeRef rangeRef) { - throw new Util.FoundOne(rangeRef); - } + public static boolean isDeterministicFuncWithSingleInputRef(RexNode expr, + final Set validInputRefs) { + boolean deterministicFuncWithSingleInputRef = true; + + RexVisitor visitor = new DeterMinisticFuncVisitorImpl() { + Set inputRefs = new HashSet(); @Override - public Void visitFieldAccess(RexFieldAccess fieldAccess) { - throw new Util.FoundOne(fieldAccess); + public Void visitInputRef(RexInputRef inputRef) { + if (validInputRefs.contains(inputRef.getIndex())) { + inputRefs.add(inputRef.getIndex()); + if (inputRefs.size() > 1) { + throw new Util.FoundOne(inputRef); + } + } else { + throw new Util.FoundOne(inputRef); + } + return null; } }; try { expr.accept(visitor); } catch (Util.FoundOne e) { - deterministicFuncOnLiterals = false; + deterministicFuncWithSingleInputRef = false; } - return deterministicFuncOnLiterals; + return deterministicFuncWithSingleInputRef; } public static ImmutableMap getColInfoMap(List hiveCols, diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveFilterProjectTransposeRule.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveFilterProjectTransposeRule.java index 1e947c3..9540cdc 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveFilterProjectTransposeRule.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveFilterProjectTransposeRule.java @@ -17,34 +17,54 @@ */ package org.apache.hadoop.hive.ql.optimizer.calcite.rules; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Project; import org.apache.calcite.rel.core.RelFactories.FilterFactory; import org.apache.calcite.rel.core.RelFactories.ProjectFactory; import org.apache.calcite.rel.rules.FilterProjectTransposeRule; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexInputRef; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexOver; +import org.apache.calcite.rex.RexUtil; +import org.apache.calcite.tools.RelBuilder; import org.apache.hadoop.hive.ql.optimizer.calcite.HiveCalciteUtil; import org.apache.hadoop.hive.ql.optimizer.calcite.HiveRelFactories; import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveProject; public class HiveFilterProjectTransposeRule extends FilterProjectTransposeRule { + public static final HiveFilterProjectTransposeRule INSTANCE_DETERMINISTIC_WINDOWING = + new HiveFilterProjectTransposeRule(Filter.class, HiveRelFactories.HIVE_FILTER_FACTORY, + HiveProject.class, HiveRelFactories.HIVE_PROJECT_FACTORY, true, true); + public static final HiveFilterProjectTransposeRule INSTANCE_DETERMINISTIC = new HiveFilterProjectTransposeRule(Filter.class, HiveRelFactories.HIVE_FILTER_FACTORY, - HiveProject.class, HiveRelFactories.HIVE_PROJECT_FACTORY, true); + HiveProject.class, HiveRelFactories.HIVE_PROJECT_FACTORY, true, false); public static final HiveFilterProjectTransposeRule INSTANCE = new HiveFilterProjectTransposeRule(Filter.class, HiveRelFactories.HIVE_FILTER_FACTORY, - HiveProject.class, HiveRelFactories.HIVE_PROJECT_FACTORY, false); + HiveProject.class, HiveRelFactories.HIVE_PROJECT_FACTORY, false, false); private final boolean onlyDeterministic; + + private final boolean pushThroughWindowing; - public HiveFilterProjectTransposeRule(Class filterClass, + private HiveFilterProjectTransposeRule(Class filterClass, FilterFactory filterFactory, Class projectClass, - ProjectFactory projectFactory, boolean onlyDeterministic) { + ProjectFactory projectFactory, boolean onlyDeterministic,boolean pushThroughWindowing) { super(filterClass, filterFactory, projectClass, projectFactory); this.onlyDeterministic = onlyDeterministic; + this.pushThroughWindowing = pushThroughWindowing; } @Override @@ -58,4 +78,107 @@ public boolean matches(RelOptRuleCall call) { return super.matches(call); } + public void onMatch(RelOptRuleCall call) { + final Filter filter = call.rel(0); + final Project origproject = call.rel(1); + RexNode filterCond = filter.getCondition(); + + if (RexUtil.containsCorrelation(filterCond)) { + // If there is a correlation condition anywhere in the filter, don't + // push this filter past project since in some cases it can prevent a + // Correlate from being de-correlated. + return; + } + + if (RexOver.containsOver(origproject.getProjects(), null)) { + if (pushThroughWindowing) { + Set commonPartitionKeys = getCommonPartitionCols(origproject.getProjects()); + List newPartKeyFilConds = new ArrayList(); + + // TODO: + // 1) Handle compound partition keys (partition by k1+k2) + // 2) When multiple window clauses are present in same select Even if + // Predicate can not pushed past all of them, we might still able to + // push + // it below some of them. + // Ex: select * from (select key, value, avg(c_int) over (partition by + // key), sum(c_float) over(partition by value) from t1)t1 where value < + // 10 + // --> select * from (select key, value, avg(c_int) over (partition by + // key) from (select key, value, sum(c_float) over(partition by value) + // from t1 where value < 10)t1)t2 + if (!commonPartitionKeys.isEmpty()) { + List conjuctiveElements = RelOptUtil.conjunctions(filterCond); + for (RexNode ce : conjuctiveElements) { + RexNode newCondition = RelOptUtil.pushPastProject(ce, origproject); + if (HiveCalciteUtil.isDeterministicFuncWithSingleInputRef(newCondition, + commonPartitionKeys)) { + newPartKeyFilConds.add(newCondition); + } + } + filterCond = RexUtil.composeConjunction(filter.getCluster().getRexBuilder(), + newPartKeyFilConds, true); + } + } else { + filterCond = null; + } + } + + if (filterCond != null) { + RelNode newProjRel = getNewProject(filterCond, origproject, filter.getCluster() + .getTypeFactory(), call.builder()); + call.transformTo(newProjRel); + } + } + + private static RelNode getNewProject(RexNode filterCondition, Project oldProj, + RelDataTypeFactory typeFactory, RelBuilder relBuilder) { + + // convert the filter to one that references the child of the project + RexNode newCondition = RelOptUtil.pushPastProject(filterCondition, oldProj); + + // Remove cast of BOOLEAN NOT NULL to BOOLEAN or vice versa. Filter accepts + // nullable and not-nullable conditions, but a CAST might get in the way of + // other rewrites. + if (RexUtil.isNullabilityCast(typeFactory, newCondition)) { + newCondition = ((RexCall) newCondition).getOperands().get(0); + } + + RelNode newFilterRel = relBuilder.push(oldProj.getInput()).filter(newCondition).build(); + + RelNode newProjRel = relBuilder.push(newFilterRel) + .project(oldProj.getProjects(), oldProj.getRowType().getFieldNames()).build(); + return newProjRel; + } + + private static Set getCommonPartitionCols(List projections) { + RexOver overClause; + boolean firstOverClause = true; + Set commonPartitionKeys = new HashSet(); + + for (RexNode expr : projections) { + if (expr instanceof RexOver) { + overClause = (RexOver) expr; + + if (firstOverClause) { + firstOverClause = false; + commonPartitionKeys.addAll(getPartitionCols(overClause.getWindow().partitionKeys)); + } else { + commonPartitionKeys.retainAll(getPartitionCols(overClause.getWindow().partitionKeys)); + } + } + } + + return commonPartitionKeys; + } + + private static List getPartitionCols(List partitionKeys) { + List pCols = new ArrayList(); + for (RexNode key : partitionKeys) { + if (key instanceof RexInputRef) { + pCols.add(((RexInputRef) key).getIndex()); + } + } + return pCols; + } } diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java index f50f4d3..ebebd8c 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java @@ -1080,11 +1080,17 @@ private RelNode applyPreJoinOrderingTransforms(RelNode basePlan, RelMetadataProv // TODO: Add in ReduceExpressionrules (Constant folding) to below once // HIVE-11927 is fixed. perfLogger.PerfLogBegin(this.getClass().getName(), PerfLogger.OPTIMIZER); - basePlan = hepPlan(basePlan, true, mdProvider, null, HiveFilterProjectTransposeRule.INSTANCE_DETERMINISTIC, - HiveFilterSetOpTransposeRule.INSTANCE, HiveFilterSortTransposeRule.INSTANCE, HiveFilterJoinRule.JOIN, - HiveFilterJoinRule.FILTER_ON_JOIN, new HiveFilterAggregateTransposeRule(Filter.class, - HiveRelFactories.HIVE_FILTER_FACTORY, Aggregate.class), new FilterMergeRule( - HiveRelFactories.HIVE_FILTER_FACTORY)); + basePlan = hepPlan( + basePlan, + true, + mdProvider, + null, + conf.getBoolVar(HiveConf.ConfVars.HIVEOPTPPD_WINDOWING) ? HiveFilterProjectTransposeRule.INSTANCE_DETERMINISTIC_WINDOWING + : HiveFilterProjectTransposeRule.INSTANCE_DETERMINISTIC, + HiveFilterSetOpTransposeRule.INSTANCE, HiveFilterSortTransposeRule.INSTANCE, + HiveFilterJoinRule.JOIN, HiveFilterJoinRule.FILTER_ON_JOIN, + new HiveFilterAggregateTransposeRule(Filter.class, HiveRelFactories.HIVE_FILTER_FACTORY, + Aggregate.class), new FilterMergeRule(HiveRelFactories.HIVE_FILTER_FACTORY)); perfLogger.PerfLogEnd(this.getClass().getName(), PerfLogger.OPTIMIZER, "Calcite: Prejoin ordering transformation, PPD for old join syntax"); @@ -1133,11 +1139,17 @@ private RelNode applyPreJoinOrderingTransforms(RelNode basePlan, RelMetadataProv // TODO: Add in ReduceExpressionrules (Constant folding) to below once // HIVE-11927 is fixed. perfLogger.PerfLogBegin(this.getClass().getName(), PerfLogger.OPTIMIZER); - basePlan = hepPlan(basePlan, true, mdProvider, null, HiveFilterProjectTransposeRule.INSTANCE_DETERMINISTIC, - HiveFilterSetOpTransposeRule.INSTANCE, HiveFilterSortTransposeRule.INSTANCE, HiveFilterJoinRule.JOIN, - HiveFilterJoinRule.FILTER_ON_JOIN, new HiveFilterAggregateTransposeRule(Filter.class, - HiveRelFactories.HIVE_FILTER_FACTORY, Aggregate.class), new FilterMergeRule( - HiveRelFactories.HIVE_FILTER_FACTORY)); + basePlan = hepPlan( + basePlan, + true, + mdProvider, + null, + conf.getBoolVar(HiveConf.ConfVars.HIVEOPTPPD_WINDOWING) ? HiveFilterProjectTransposeRule.INSTANCE_DETERMINISTIC_WINDOWING + : HiveFilterProjectTransposeRule.INSTANCE_DETERMINISTIC, + HiveFilterSetOpTransposeRule.INSTANCE, HiveFilterSortTransposeRule.INSTANCE, + HiveFilterJoinRule.JOIN, HiveFilterJoinRule.FILTER_ON_JOIN, + new HiveFilterAggregateTransposeRule(Filter.class, HiveRelFactories.HIVE_FILTER_FACTORY, + Aggregate.class), new FilterMergeRule(HiveRelFactories.HIVE_FILTER_FACTORY)); perfLogger.PerfLogEnd(this.getClass().getName(), PerfLogger.OPTIMIZER, "Calcite: Prejoin ordering transformation, Constant propagation and PPD"); diff --git a/ql/src/test/queries/clientpositive/ppd_windowing1.q b/ql/src/test/queries/clientpositive/ppd_windowing1.q new file mode 100644 index 0000000..ccf133f --- /dev/null +++ b/ql/src/test/queries/clientpositive/ppd_windowing1.q @@ -0,0 +1,46 @@ +set hive.optimize.ppd=true; +set hive.ppd.remove.duplicatefilters=false; + + +-- Test simple PPD through Windowing +EXPLAIN select * from (SELECT key, sum(key) (partition by key) as c1 from src)r1 where key > '2'; +EXPLAIN select * from (SELECT key, sum(key) (partition by key) as c1 from src)r1 where key > 2; +EXPLAIN select * from (SELECT key, sum(key) (partition by key) as c1 from src)r1 where cast(key as int) > 2; +EXPLAIN select * from (SELECT key, sum(key) (partition by key) as c1 from src)r1 where (cast(key as int) + 1) > 2; +EXPLAIN select * from (SELECT (cast(key as int))+2 as key, sum(key) (partition by key) as c1 from src)r1 where (cast(key as int) + 1) > 2; + + +-- Test PPD through Windowing where predicate is a subset of partition keys +EXPLAIN select * from (SELECT key, sum(key) (partition by key, value) as c1 from src)r1 where key > '2'; +EXPLAIN select * from (SELECT key, sum(key) (partition by key, value) as c1 from src)r1 where key > 2; +EXPLAIN select * from (SELECT key, sum(key) (partition by key, value) as c1 from src)r1 where cast(key as int) > 2; +EXPLAIN select * from (SELECT key, sum(key) (partition by key, value) as c1 from src)r1 where (cast(key as int) + 1) > 2; +EXPLAIN select * from (SELECT (cast(key as int))+2 as key, sum(key) (partition by key, value) as c1 from src)r1 where (cast(key as int) + 1) > 2; + + +-- Test PPD through Windowing where predicate is a subset of partition keys, multiple windows are involved and UDAF is same +EXPLAIN select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(key) (partition by key) as c2 from src)r1 where key > '2'; +EXPLAIN select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(key) (partition by key) as c2 from src)r1 where key > 2; +EXPLAIN select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(key) (partition by key) as c2 from src)r1 where (cast(key as int) + 1) > 2; +EXPLAIN select * from (SELECT (cast(key as int))+2 as key, sum(key) (partition by key,value) as c1, sum(key) (partition by key) as c2 from src)r1 where (cast(key as int) + 1) > 2; + + +-- Test PPD through Windowing where predicate is a subset of partition keys, multiple windows are involved and UDAF has different args +EXPLAIN select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(value) (partition by key) as c2 from src)r1 where key > '2'; +EXPLAIN select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(value) (partition by key) as c2 from src)r1 where key > 2; +EXPLAIN select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(value) (partition by key) as c2 from src)r1 where (cast(key as int) + 1) > 2; +EXPLAIN select * from (SELECT (cast(key as int))+2 as key, sum(key) (partition by key,value) as c1, sum(value) (partition by key) as c2 from src)r1 where (cast(key as int) + 1) > 2; + + +-- Test predicate is not getting pushed down when multiple windows are involved and they don't have common partition keys +EXPLAIN select * from (SELECT key, sum(key) (partition by key,value) as c1, avg(value) (partition by value) as c2 from src)r1 where key > '2'; + + +-- Test predicate is not getting pushed down when window has compound partition key +EXPLAIN select * from (SELECT key, sum(key) (partition by key + 2) as c1 from src)r1 where key > '2'; +EXPLAIN select * from (SELECT key, sum(key) (partition by key + value) as c1 from src)r1 where key > '2'; + +-- Test predicate is not getting pushed down when predicate involves more than one col +EXPLAIN select * from (SELECT key, value, sum(key) (partition by key, value) as c1 from src)r1 where (key + value) > '2'; +EXPLAIN select * from (SELECT key, value, sum(key) (partition by key + value) as c1 from src)r1 where (key + value) > '2'; +EXPLAIN select * from (SELECT (cast(key as int))+(cast(value as int)) as key, sum(key) (partition by key) as c1 from src)r1 where key > 2; diff --git a/ql/src/test/queries/clientpositive/ppd_windowing2.q b/ql/src/test/queries/clientpositive/ppd_windowing2.q new file mode 100644 index 0000000..b051551 --- /dev/null +++ b/ql/src/test/queries/clientpositive/ppd_windowing2.q @@ -0,0 +1,47 @@ +set hive.optimize.ppd=true; +set hive.ppd.remove.duplicatefilters=false; + +-- NOTE: This is a correctness test. If you regen q.out, regen it with optimization turned off + +-- Test simple PPD through Windowing +select * from (SELECT key, sum(key) (partition by key) as c1 from src)r1 where key > '2'; +select * from (SELECT key, sum(key) (partition by key) as c1 from src)r1 where key > 2; +select * from (SELECT key, sum(key) (partition by key) as c1 from src)r1 where cast(key as int) > 2; +select * from (SELECT key, sum(key) (partition by key) as c1 from src)r1 where (cast(key as int) + 1) > 2; +select * from (SELECT (cast(key as int))+2 as key, sum(key) (partition by key) as c1 from src)r1 where (cast(key as int) + 1) > 2; + + +-- Test PPD through Windowing where predicate is a subset of partition keys +select * from (SELECT key, sum(key) (partition by key, value) as c1 from src)r1 where key > '2'; +select * from (SELECT key, sum(key) (partition by key, value) as c1 from src)r1 where key > 2; +select * from (SELECT key, sum(key) (partition by key, value) as c1 from src)r1 where cast(key as int) > 2; +select * from (SELECT key, sum(key) (partition by key, value) as c1 from src)r1 where (cast(key as int) + 1) > 2; +select * from (SELECT (cast(key as int))+2 as key, sum(key) (partition by key, value) as c1 from src)r1 where (cast(key as int) + 1) > 2; + + +-- Test PPD through Windowing where predicate is a subset of partition keys, multiple windows are involved and UDAF is same +select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(key) (partition by key) as c2 from src)r1 where key > '2'; +select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(key) (partition by key) as c2 from src)r1 where key > 2; +select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(key) (partition by key) as c2 from src)r1 where (cast(key as int) + 1) > 2; +select * from (SELECT (cast(key as int))+2 as key, sum(key) (partition by key,value) as c1, sum(key) (partition by key) as c2 from src)r1 where (cast(key as int) + 1) > 2; + + +-- Test PPD through Windowing where predicate is a subset of partition keys, multiple windows are involved and UDAF has different args +select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(value) (partition by key) as c2 from src)r1 where key > '2'; +select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(value) (partition by key) as c2 from src)r1 where key > 2; +select * from (SELECT key, sum(key) (partition by key,value) as c1, sum(value) (partition by key) as c2 from src)r1 where (cast(key as int) + 1) > 2; +select * from (SELECT (cast(key as int))+2 as key, sum(key) (partition by key,value) as c1, sum(value) (partition by key) as c2 from src)r1 where (cast(key as int) + 1) > 2; + + +-- Test predicate is not getting pushed down when multiple windows are involved and they don't have common partition keys +select * from (SELECT key, sum(key) (partition by key,value) as c1, avg(value) (partition by value) as c2 from src)r1 where key > '2'; + + +-- Test predicate is not getting pushed down when window has compound partition key +select * from (SELECT key, sum(key) (partition by key + 2) as c1 from src)r1 where key > '2'; +select * from (SELECT key, sum(key) (partition by key + value) as c1 from src)r1 where key > '2'; + +-- Test predicate is not getting pushed down when predicate involves more than one col +select * from (SELECT key, value, sum(key) (partition by key, value) as c1 from src)r1 where (key + value) > '2'; +select * from (SELECT key, value, sum(key) (partition by key + value) as c1 from src)r1 where (key + value) > '2'; +select * from (SELECT (cast(key as int))+(cast(value as int)) as key, sum(key) (partition by key) as c1 from src)r1 where key > 2;