julianhyde commented on code in PR #4246:
URL: https://github.com/apache/calcite/pull/4246#discussion_r2001730461
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -44,25 +48,16 @@
*
* <h2>Example</h2>
*
- * <p>Query: <code>R1 Intersect All R2</code>
+ * <p>Query: <code>R1 Intersect R2</code>
Review Comment:
Can you revise this whole section? The previous author used terms such as
'GB' (which is used in Hive but not in Calcite). I suspect that SQL queries are
clearer than pseudo-relational algebra.
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
+ relBuilder.literal(i))).as(countPrefix + i);
}
// create a union above all the branches
- final int branchCount = intersect.getInputs().size();
- relBuilder.union(true, branchCount);
+ relBuilder.union(true, inputCount);
final RelNode union = relBuilder.peek();
-
- // 2nd level GB: create a GB (col0, col1, count(c)) for each branch
- // the index of c is union.getRowType().getFieldList().size() - 1
final int fieldCount = union.getRowType().getFieldCount();
- final ImmutableBitSet groupSet =
- ImmutableBitSet.range(fieldCount - 1);
- relBuilder.aggregate(relBuilder.groupKey(groupSet),
- relBuilder.countStar(null));
+ // Add aggCalls
+
relBuilder.aggregate(relBuilder.groupKey(ImmutableBitSet.range(fieldCount)),
aggCalls);
+
+ // Generate filter count_i{n} > 0 for each branch
+ RexNode[] filters = new RexNode[inputCount];
+ for (int i = 0; i < inputCount; i++) {
+ filters[i] =
+ relBuilder.greaterThan(relBuilder.field(countPrefix + i),
relBuilder.literal(0));
+ }
- // add a filter count(c) = #branches
- relBuilder.filter(
- relBuilder.equals(relBuilder.field(fieldCount - 1),
- rexBuilder.makeBigintLiteral(new BigDecimal(branchCount))));
+ // Add filter count_i{n} > 0 for each branch
+ relBuilder.filter(relBuilder.and(filters));
Review Comment:
`relBuilder.filter(relBuilder.and(filters))` →
`relBuilder.filter(filters)`
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
+ relBuilder.literal(i))).as(countPrefix + i);
}
// create a union above all the branches
- final int branchCount = intersect.getInputs().size();
- relBuilder.union(true, branchCount);
+ relBuilder.union(true, inputCount);
final RelNode union = relBuilder.peek();
-
- // 2nd level GB: create a GB (col0, col1, count(c)) for each branch
- // the index of c is union.getRowType().getFieldList().size() - 1
final int fieldCount = union.getRowType().getFieldCount();
- final ImmutableBitSet groupSet =
- ImmutableBitSet.range(fieldCount - 1);
- relBuilder.aggregate(relBuilder.groupKey(groupSet),
- relBuilder.countStar(null));
+ // Add aggCalls
+
relBuilder.aggregate(relBuilder.groupKey(ImmutableBitSet.range(fieldCount)),
aggCalls);
+
+ // Generate filter count_i{n} > 0 for each branch
+ RexNode[] filters = new RexNode[inputCount];
Review Comment:
`List<RexNode>` is simpler than `RexNode[]`.
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
+ relBuilder.literal(i))).as(countPrefix + i);
}
// create a union above all the branches
- final int branchCount = intersect.getInputs().size();
- relBuilder.union(true, branchCount);
+ relBuilder.union(true, inputCount);
final RelNode union = relBuilder.peek();
-
- // 2nd level GB: create a GB (col0, col1, count(c)) for each branch
- // the index of c is union.getRowType().getFieldList().size() - 1
final int fieldCount = union.getRowType().getFieldCount();
- final ImmutableBitSet groupSet =
- ImmutableBitSet.range(fieldCount - 1);
- relBuilder.aggregate(relBuilder.groupKey(groupSet),
- relBuilder.countStar(null));
+ // Add aggCalls
+
relBuilder.aggregate(relBuilder.groupKey(ImmutableBitSet.range(fieldCount)),
aggCalls);
+
+ // Generate filter count_i{n} > 0 for each branch
+ RexNode[] filters = new RexNode[inputCount];
+ for (int i = 0; i < inputCount; i++) {
+ filters[i] =
+ relBuilder.greaterThan(relBuilder.field(countPrefix + i),
relBuilder.literal(0));
+ }
- // add a filter count(c) = #branches
- relBuilder.filter(
- relBuilder.equals(relBuilder.field(fieldCount - 1),
- rexBuilder.makeBigintLiteral(new BigDecimal(branchCount))));
+ // Add filter count_i{n} > 0 for each branch
+ relBuilder.filter(relBuilder.and(filters));
- // Project all but the last field
- relBuilder.project(Util.skipLast(relBuilder.fields()));
+ // Project all but the last added field(e.g. i and count_i{n})
+ relBuilder.project(Util.skipLast(relBuilder.fields(),
relBuilder.fields().size() - oriFieldCount));
Review Comment:
add static import for `Util.skipLast`
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
Review Comment:
inline `countPrefix`. no need for a variable (when you start using field
ordinals rather than field names)
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
+ relBuilder.literal(i))).as(countPrefix + i);
}
// create a union above all the branches
- final int branchCount = intersect.getInputs().size();
Review Comment:
i prefer the old name, `branchCount`, to `inputCount`.
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
Review Comment:
use list rather than array
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
+ relBuilder.literal(i))).as(countPrefix + i);
}
// create a union above all the branches
- final int branchCount = intersect.getInputs().size();
- relBuilder.union(true, branchCount);
+ relBuilder.union(true, inputCount);
final RelNode union = relBuilder.peek();
-
- // 2nd level GB: create a GB (col0, col1, count(c)) for each branch
- // the index of c is union.getRowType().getFieldList().size() - 1
final int fieldCount = union.getRowType().getFieldCount();
- final ImmutableBitSet groupSet =
- ImmutableBitSet.range(fieldCount - 1);
- relBuilder.aggregate(relBuilder.groupKey(groupSet),
- relBuilder.countStar(null));
+ // Add aggCalls
+
relBuilder.aggregate(relBuilder.groupKey(ImmutableBitSet.range(fieldCount)),
aggCalls);
+
+ // Generate filter count_i{n} > 0 for each branch
+ RexNode[] filters = new RexNode[inputCount];
+ for (int i = 0; i < inputCount; i++) {
+ filters[i] =
+ relBuilder.greaterThan(relBuilder.field(countPrefix + i),
relBuilder.literal(0));
+ }
- // add a filter count(c) = #branches
- relBuilder.filter(
- relBuilder.equals(relBuilder.field(fieldCount - 1),
- rexBuilder.makeBigintLiteral(new BigDecimal(branchCount))));
+ // Add filter count_i{n} > 0 for each branch
+ relBuilder.filter(relBuilder.and(filters));
- // Project all but the last field
- relBuilder.project(Util.skipLast(relBuilder.fields()));
+ // Project all but the last added field(e.g. i and count_i{n})
+ relBuilder.project(Util.skipLast(relBuilder.fields(),
relBuilder.fields().size() - oriFieldCount));
Review Comment:
I have a feeling that `skipLast(list, list.size() - n)` can be simplified
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
Review Comment:
don't use `indexAlias` (a string); use an `int`
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
+ relBuilder.literal(i))).as(countPrefix + i);
}
// create a union above all the branches
- final int branchCount = intersect.getInputs().size();
- relBuilder.union(true, branchCount);
+ relBuilder.union(true, inputCount);
final RelNode union = relBuilder.peek();
-
- // 2nd level GB: create a GB (col0, col1, count(c)) for each branch
- // the index of c is union.getRowType().getFieldList().size() - 1
final int fieldCount = union.getRowType().getFieldCount();
- final ImmutableBitSet groupSet =
- ImmutableBitSet.range(fieldCount - 1);
- relBuilder.aggregate(relBuilder.groupKey(groupSet),
- relBuilder.countStar(null));
+ // Add aggCalls
+
relBuilder.aggregate(relBuilder.groupKey(ImmutableBitSet.range(fieldCount)),
aggCalls);
+
+ // Generate filter count_i{n} > 0 for each branch
+ RexNode[] filters = new RexNode[inputCount];
+ for (int i = 0; i < inputCount; i++) {
+ filters[i] =
+ relBuilder.greaterThan(relBuilder.field(countPrefix + i),
relBuilder.literal(0));
Review Comment:
again, use `field(int)` rather than `field(String)`
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
+ relBuilder.literal(i))).as(countPrefix + i);
Review Comment:
fix indent
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
Review Comment:
why bigint not int?
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
Review Comment:
You've removed more comments than you've added. This method doesn't need
line-by-line comments but a 'here's the overall plan' comment is necessary.
Give a good example of the SQL you intend to generate.
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToDistinctRule.java:
##########
@@ -96,39 +91,48 @@ public IntersectToDistinctRule(Class<? extends Intersect>
intersectClass,
final RelOptCluster cluster = intersect.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RelBuilder relBuilder = call.builder();
-
- // 1st level GB: create a GB (col0, col1, count() as c) for each branch
- for (RelNode input : intersect.getInputs()) {
- relBuilder.push(input);
- relBuilder.aggregate(relBuilder.groupKey(relBuilder.fields()),
- relBuilder.countStar(null));
+ final String countPrefix = "count_i";
+ final String indexAlias = "i";
+ final int oriFieldCount = intersect.getRowType().getFieldCount();
+ final int inputCount = intersect.getInputs().size();
+
+ AggCall[] aggCalls = new AggCall[inputCount];
+ for (int i = 0; i < inputCount; ++i) {
+ relBuilder.push(intersect.getInputs().get(i));
+ List<RexNode> fields = new ArrayList<>(relBuilder.fields());
+ // Add a constant column "i" for each input
+ fields.add(
+ relBuilder.alias(
+ rexBuilder.makeBigintLiteral(new BigDecimal(i)), indexAlias));
+ relBuilder.project(fields);
+ // Generate count(*) filter (where i = n) as count_i{n}
+ aggCalls[i] = relBuilder.countStar(null)
+ .filter(
+ relBuilder.equals(relBuilder.field(indexAlias),
+ relBuilder.literal(i))).as(countPrefix + i);
}
// create a union above all the branches
- final int branchCount = intersect.getInputs().size();
- relBuilder.union(true, branchCount);
+ relBuilder.union(true, inputCount);
final RelNode union = relBuilder.peek();
-
- // 2nd level GB: create a GB (col0, col1, count(c)) for each branch
- // the index of c is union.getRowType().getFieldList().size() - 1
final int fieldCount = union.getRowType().getFieldCount();
- final ImmutableBitSet groupSet =
- ImmutableBitSet.range(fieldCount - 1);
- relBuilder.aggregate(relBuilder.groupKey(groupSet),
- relBuilder.countStar(null));
+ // Add aggCalls
+
relBuilder.aggregate(relBuilder.groupKey(ImmutableBitSet.range(fieldCount)),
aggCalls);
+
+ // Generate filter count_i{n} > 0 for each branch
+ RexNode[] filters = new RexNode[inputCount];
+ for (int i = 0; i < inputCount; i++) {
+ filters[i] =
+ relBuilder.greaterThan(relBuilder.field(countPrefix + i),
relBuilder.literal(0));
+ }
- // add a filter count(c) = #branches
- relBuilder.filter(
- relBuilder.equals(relBuilder.field(fieldCount - 1),
- rexBuilder.makeBigintLiteral(new BigDecimal(branchCount))));
+ // Add filter count_i{n} > 0 for each branch
+ relBuilder.filter(relBuilder.and(filters));
- // Project all but the last field
- relBuilder.project(Util.skipLast(relBuilder.fields()));
+ // Project all but the last added field(e.g. i and count_i{n})
Review Comment:
add space before '('
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]