diff --git ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveAggregateJoinTransposeRule.java ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveAggregateJoinTransposeRule.java index c59af39..b4f7229 100644 --- ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveAggregateJoinTransposeRule.java +++ ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveAggregateJoinTransposeRule.java @@ -94,6 +94,18 @@ public void onMatch(RelOptRuleCall call) { final Join join = call.rel(1); final RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder(); + // Check if we have visited this operator in this rule; + // if we have not, register it + HiveRulesRegistry registry = call.getPlanner(). + getContext().unwrap(HiveRulesRegistry.class); + if (registry != null) { + if (registry.getVisited(this).contains(aggregate)) { + return; + } else { + registry.registerVisited(this, aggregate); + } + } + // If any aggregate functions do not support splitting, bail out // If any aggregate call has a filter, bail out for (AggregateCall aggregateCall : aggregate.getAggCallList()) { @@ -176,9 +188,16 @@ public void onMatch(RelOptRuleCall call) { // unique = true; } else { - final Boolean unique0 = - RelMetadataQuery.areColumnsUnique(joinInput, belowAggregateKey); - unique = unique0 != null && unique0; + // Finding out whether the input is already unique requires a call + // to areColumnsUnique that currently (until [CALCITE-794] "Detect + // cycles when computing statistics" is fixed) places a heavy load on + // the metadata system. + // + // So we choose to imagine that the input is not unique. This could + // create infinite loops if the Hive rules registry is not used; we + // solve this problem by using it + // + unique = false; } if (unique) { ++uniqueCount; @@ -295,6 +314,12 @@ public Integer apply(Integer a0) { Mappings.apply(mapping, aggregate.getGroupSet()), Mappings.apply2(mapping, aggregate.getGroupSets()), newAggCalls); } + + // We register the new aggregate so we do not fire the rule on it again + if (registry != null) { + registry.registerVisited(this, r); + } + call.transformTo(r); // Add original tree as well for potential alternative transformation. // This is modeled after LoptOptimizeJoinRule::findBestOrderings() in diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java index c005b1a..579fa9e 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java @@ -932,9 +932,9 @@ public RelNode apply(RelOptCluster cluster, RelOptSchema relOptSchema, SchemaPlu HepProgramBuilder hepPgmBldr = new HepProgramBuilder().addMatchOrder(HepMatchOrder.BOTTOM_UP); hepPgmBldr.addRuleInstance(HiveAggregateJoinTransposeRule.INSTANCE); - HepProgram hepPgm = hepPgmBldr.build(); - HepPlanner hepPlanner = new HepPlanner(hepPgm); - + HiveRulesRegistry registry = new HiveRulesRegistry(); + HiveHepPlannerContext context = new HiveHepPlannerContext(registry); + HepPlanner hepPlanner = new HepPlanner(hepPgmBldr.build(), context); List list = Lists.newArrayList(); list.add(mdProvider.getMetadataProvider()); hepPlanner.registerMetadataProviders(list);