You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by ru...@apache.org on 2019/07/25 07:04:27 UTC
[calcite] branch master updated: [CALCITE-3109] Improvements on
algebraic operators to express recursive queries (RepeatUnion & TableSpool)
This is an automated email from the ASF dual-hosted git repository.
rubenql pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new c1c4e31 [CALCITE-3109] Improvements on algebraic operators to express recursive queries (RepeatUnion & TableSpool)
c1c4e31 is described below
commit c1c4e31c849c4c9cb73056be95f5694ccd5fc2db
Author: rubenada <ru...@gmail.com>
AuthorDate: Thu Jun 13 12:18:38 2019 +0200
[CALCITE-3109] Improvements on algebraic operators to express recursive queries (RepeatUnion & TableSpool)
---
.../adapter/enumerable/EnumerableRepeatUnion.java | 10 ++--
.../enumerable/EnumerableRepeatUnionRule.java | 2 +-
.../adapter/enumerable/EnumerableTableSpool.java | 12 +++--
.../enumerable/EnumerableTableSpoolRule.java | 2 +-
.../org/apache/calcite/rel/core/RelFactories.java | 12 ++---
.../org/apache/calcite/rel/core/RepeatUnion.java | 21 ++++-----
.../org/apache/calcite/rel/core/TableSpool.java | 13 +++---
.../calcite/rel/logical/LogicalRepeatUnion.java | 10 ++--
.../calcite/rel/logical/LogicalTableSpool.java | 12 ++---
.../java/org/apache/calcite/tools/RelBuilder.java | 54 +++++++++++++++++-----
.../org/apache/calcite/test/RelBuilderTest.java | 8 ++--
.../EnumerableRepeatUnionHierarchyTest.java | 8 ++--
.../apache/calcite/linq4j/EnumerableDefaults.java | 15 +++---
13 files changed, 105 insertions(+), 74 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRepeatUnion.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRepeatUnion.java
index c845070..33b234a 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRepeatUnion.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRepeatUnion.java
@@ -42,14 +42,14 @@ public class EnumerableRepeatUnion extends RepeatUnion implements EnumerableRel
* Creates an EnumerableRepeatUnion.
*/
EnumerableRepeatUnion(RelOptCluster cluster, RelTraitSet traitSet,
- RelNode seed, RelNode iterative, boolean all, int maxRep) {
- super(cluster, traitSet, seed, iterative, all, maxRep);
+ RelNode seed, RelNode iterative, boolean all, int iterationLimit) {
+ super(cluster, traitSet, seed, iterative, all, iterationLimit);
}
@Override public EnumerableRepeatUnion copy(RelTraitSet traitSet, List<RelNode> inputs) {
assert inputs.size() == 2;
return new EnumerableRepeatUnion(getCluster(), traitSet,
- inputs.get(0), inputs.get(1), all, maxRep);
+ inputs.get(0), inputs.get(1), all, iterationLimit);
}
@Override public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
@@ -58,7 +58,7 @@ public class EnumerableRepeatUnion extends RepeatUnion implements EnumerableRel
"Only EnumerableRepeatUnion ALL is supported");
}
- // return repeatUnionAll(<seedExp>, <iterativeExp>, maxRep);
+ // return repeatUnionAll(<seedExp>, <iterativeExp>, iterationLimit);
BlockBuilder builder = new BlockBuilder();
RelNode seed = getSeedRel();
@@ -74,7 +74,7 @@ public class EnumerableRepeatUnion extends RepeatUnion implements EnumerableRel
BuiltInMethod.REPEAT_UNION_ALL.method,
seedExp,
iterativeExp,
- Expressions.constant(maxRep, int.class));
+ Expressions.constant(iterationLimit, int.class));
builder.add(unionExp);
PhysType physType = PhysTypeImpl.of(
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRepeatUnionRule.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRepeatUnionRule.java
index b7e78d4..b57118a 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRepeatUnionRule.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRepeatUnionRule.java
@@ -49,7 +49,7 @@ public class EnumerableRepeatUnionRule extends ConverterRule {
convert(seedRel, seedRel.getTraitSet().replace(out)),
convert(iterativeRel, iterativeRel.getTraitSet().replace(out)),
union.all,
- union.maxRep);
+ union.iterationLimit);
}
}
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableSpool.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableSpool.java
index 6e726ec..2712453 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableSpool.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableSpool.java
@@ -21,6 +21,7 @@ import org.apache.calcite.linq4j.tree.BlockBuilder;
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.linq4j.tree.Expressions;
import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelCollationTraitDef;
import org.apache.calcite.rel.RelDistributionTraitDef;
@@ -44,13 +45,13 @@ import org.apache.calcite.util.BuiltInMethod;
public class EnumerableTableSpool extends TableSpool implements EnumerableRel {
private EnumerableTableSpool(RelOptCluster cluster, RelTraitSet traitSet,
- RelNode input, Type readType, Type writeType, String tableName) {
- super(cluster, traitSet, input, readType, writeType, tableName);
+ RelNode input, Type readType, Type writeType, RelOptTable table) {
+ super(cluster, traitSet, input, readType, writeType, table);
}
/** Creates an EnumerableTableSpool. */
public static EnumerableTableSpool create(RelNode input, Type readType,
- Type writeType, String tableName) {
+ Type writeType, RelOptTable table) {
RelOptCluster cluster = input.getCluster();
RelMetadataQuery mq = cluster.getMetadataQuery();
RelTraitSet traitSet = cluster.traitSetOf(EnumerableConvention.INSTANCE)
@@ -58,7 +59,7 @@ public class EnumerableTableSpool extends TableSpool implements EnumerableRel {
() -> mq.collations(input))
.replaceIf(RelDistributionTraitDef.INSTANCE,
() -> mq.distribution(input));
- return new EnumerableTableSpool(cluster, traitSet, input, readType, writeType, tableName);
+ return new EnumerableTableSpool(cluster, traitSet, input, readType, writeType, table);
}
@Override public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
@@ -76,6 +77,7 @@ public class EnumerableTableSpool extends TableSpool implements EnumerableRel {
RelNode input = getInput();
Result inputResult = implementor.visitChild(this, 0, (EnumerableRel) input, pref);
+ String tableName = table.getQualifiedName().get(table.getQualifiedName().size() - 1);
Expression tableExp = Expressions.convert_(
Expressions.call(
Expressions.call(
@@ -106,7 +108,7 @@ public class EnumerableTableSpool extends TableSpool implements EnumerableRel {
@Override protected Spool copy(RelTraitSet traitSet, RelNode input,
Type readType, Type writeType) {
return new EnumerableTableSpool(input.getCluster(), traitSet, input,
- readType, writeType, tableName);
+ readType, writeType, table);
}
}
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableSpoolRule.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableSpoolRule.java
index 27def0a..e5e6daf 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableSpoolRule.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableSpoolRule.java
@@ -46,7 +46,7 @@ public class EnumerableTableSpoolRule extends ConverterRule {
spool.getInput().getTraitSet().replace(EnumerableConvention.INSTANCE)),
spool.readType,
spool.writeType,
- spool.getTableName());
+ spool.getTable());
}
}
diff --git a/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java b/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java
index ff8af92..55127ff 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java
@@ -619,7 +619,7 @@ public class RelFactories {
public interface SpoolFactory {
/** Creates a {@link TableSpool}. */
RelNode createTableSpool(RelNode input, Spool.Type readType,
- Spool.Type writeType, String tableName);
+ Spool.Type writeType, RelOptTable table);
}
/**
@@ -628,8 +628,8 @@ public class RelFactories {
*/
private static class SpoolFactoryImpl implements SpoolFactory {
public RelNode createTableSpool(RelNode input, Spool.Type readType,
- Spool.Type writeType, String tableName) {
- return LogicalTableSpool.create(input, readType, writeType, tableName);
+ Spool.Type writeType, RelOptTable table) {
+ return LogicalTableSpool.create(input, readType, writeType, table);
}
}
@@ -641,7 +641,7 @@ public class RelFactories {
public interface RepeatUnionFactory {
/** Creates a {@link RepeatUnion}. */
RelNode createRepeatUnion(RelNode seed, RelNode iterative, boolean all,
- int maxRep);
+ int iterationLimit);
}
/**
@@ -650,8 +650,8 @@ public class RelFactories {
*/
private static class RepeatUnionFactoryImpl implements RepeatUnionFactory {
public RelNode createRepeatUnion(RelNode seed, RelNode iterative,
- boolean all, int maxRep) {
- return LogicalRepeatUnion.create(seed, iterative, all, maxRep);
+ boolean all, int iterationLimit) {
+ return LogicalRepeatUnion.create(seed, iterative, all, iterationLimit);
}
}
}
diff --git a/core/src/main/java/org/apache/calcite/rel/core/RepeatUnion.java b/core/src/main/java/org/apache/calcite/rel/core/RepeatUnion.java
index 8d8eb52..8d76298 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/RepeatUnion.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/RepeatUnion.java
@@ -58,36 +58,33 @@ public abstract class RepeatUnion extends BiRel {
public final boolean all;
/**
- * Maximum number of times to repeat the iterative relational expression; -1
- * means no limit, 0 means only seed will be evaluated
+ * Maximum number of times to repeat the iterative relational expression;
+ * negative value means no limit, 0 means only seed will be evaluated
*/
- public final int maxRep;
+ public final int iterationLimit;
//~ Constructors -----------------------------------------------------------
protected RepeatUnion(RelOptCluster cluster, RelTraitSet traitSet,
- RelNode seed, RelNode iterative, boolean all, int maxRep) {
+ RelNode seed, RelNode iterative, boolean all, int iterationLimit) {
super(cluster, traitSet, seed, iterative);
- if (maxRep < -1) {
- throw new IllegalArgumentException("Wrong maxRep value");
- }
- this.maxRep = maxRep;
+ this.iterationLimit = iterationLimit;
this.all = all;
}
@Override public double estimateRowCount(RelMetadataQuery mq) {
// TODO implement a more accurate row count?
double seedRowCount = mq.getRowCount(getSeedRel());
- if (maxRep == 0) {
+ if (iterationLimit == 0) {
return seedRowCount;
}
return seedRowCount
- + mq.getRowCount(getIterativeRel()) * (maxRep != -1 ? maxRep : 10);
+ + mq.getRowCount(getIterativeRel()) * (iterationLimit < 0 ? 10 : iterationLimit);
}
@Override public RelWriter explainTerms(RelWriter pw) {
super.explainTerms(pw);
- if (maxRep != -1) {
- pw.item("maxRep", maxRep);
+ if (iterationLimit >= 0) {
+ pw.item("iterationLimit", iterationLimit);
}
return pw.item("all", all);
}
diff --git a/core/src/main/java/org/apache/calcite/rel/core/TableSpool.java b/core/src/main/java/org/apache/calcite/rel/core/TableSpool.java
index d7d8bc7..22506fb 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/TableSpool.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/TableSpool.java
@@ -18,6 +18,7 @@ package org.apache.calcite.rel.core;
import org.apache.calcite.linq4j.function.Experimental;
import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelWriter;
@@ -33,21 +34,21 @@ import java.util.Objects;
@Experimental
public abstract class TableSpool extends Spool {
- protected final String tableName;
+ protected final RelOptTable table;
protected TableSpool(RelOptCluster cluster, RelTraitSet traitSet,
- RelNode input, Type readType, Type writeType, String tableName) {
+ RelNode input, Type readType, Type writeType, RelOptTable table) {
super(cluster, traitSet, input, readType, writeType);
- this.tableName = Objects.requireNonNull(tableName);
+ this.table = Objects.requireNonNull(table);
}
- public String getTableName() {
- return tableName;
+ public RelOptTable getTable() {
+ return table;
}
@Override public RelWriter explainTerms(RelWriter pw) {
super.explainTerms(pw);
- return pw.item("tableName", tableName);
+ return pw.item("table", table.getQualifiedName());
}
}
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalRepeatUnion.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalRepeatUnion.java
index c0c0a32..0a74382 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalRepeatUnion.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalRepeatUnion.java
@@ -37,8 +37,8 @@ public class LogicalRepeatUnion extends RepeatUnion {
//~ Constructors -----------------------------------------------------------
private LogicalRepeatUnion(RelOptCluster cluster, RelTraitSet traitSet,
- RelNode seed, RelNode iterative, boolean all, int maxRep) {
- super(cluster, traitSet, seed, iterative, all, maxRep);
+ RelNode seed, RelNode iterative, boolean all, int iterationLimit) {
+ super(cluster, traitSet, seed, iterative, all, iterationLimit);
}
/** Creates a LogicalRepeatUnion. */
@@ -49,10 +49,10 @@ public class LogicalRepeatUnion extends RepeatUnion {
/** Creates a LogicalRepeatUnion. */
public static LogicalRepeatUnion create(RelNode seed, RelNode iterative,
- boolean all, int maxRep) {
+ boolean all, int iterationLimit) {
RelOptCluster cluster = seed.getCluster();
RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE);
- return new LogicalRepeatUnion(cluster, traitSet, seed, iterative, all, maxRep);
+ return new LogicalRepeatUnion(cluster, traitSet, seed, iterative, all, iterationLimit);
}
//~ Methods ----------------------------------------------------------------
@@ -62,7 +62,7 @@ public class LogicalRepeatUnion extends RepeatUnion {
assert traitSet.containsIfApplicable(Convention.NONE);
assert inputs.size() == 2;
return new LogicalRepeatUnion(getCluster(), traitSet,
- inputs.get(0), inputs.get(1), all, maxRep);
+ inputs.get(0), inputs.get(1), all, iterationLimit);
}
}
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableSpool.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableSpool.java
index 8b02985..c7dc798 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableSpool.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableSpool.java
@@ -19,6 +19,7 @@ package org.apache.calcite.rel.logical;
import org.apache.calcite.linq4j.function.Experimental;
import org.apache.calcite.plan.Convention;
import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelCollationTraitDef;
import org.apache.calcite.rel.RelDistributionTraitDef;
@@ -39,13 +40,13 @@ public class LogicalTableSpool extends TableSpool {
//~ Constructors -----------------------------------------------------------
public LogicalTableSpool(RelOptCluster cluster, RelTraitSet traitSet, RelNode input,
- Type readType, Type writeType, String tableName) {
- super(cluster, traitSet, input, readType, writeType, tableName);
+ Type readType, Type writeType, RelOptTable table) {
+ super(cluster, traitSet, input, readType, writeType, table);
}
/** Creates a LogicalTableSpool. */
public static LogicalTableSpool create(RelNode input, Type readType,
- Type writeType, String tableName) {
+ Type writeType, RelOptTable table) {
RelOptCluster cluster = input.getCluster();
RelMetadataQuery mq = cluster.getMetadataQuery();
RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE)
@@ -53,8 +54,7 @@ public class LogicalTableSpool extends TableSpool {
() -> mq.collations(input))
.replaceIf(RelDistributionTraitDef.INSTANCE,
() -> mq.distribution(input));
- return new LogicalTableSpool(cluster, traitSet, input, readType, writeType,
- tableName);
+ return new LogicalTableSpool(cluster, traitSet, input, readType, writeType, table);
}
//~ Methods ----------------------------------------------------------------
@@ -62,7 +62,7 @@ public class LogicalTableSpool extends TableSpool {
@Override protected Spool copy(RelTraitSet traitSet, RelNode input,
Type readType, Type writeType) {
return new LogicalTableSpool(input.getCluster(), traitSet, input,
- readType, writeType, tableName);
+ readType, writeType, table);
}
}
diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index f19a510..da28f3f 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -30,6 +30,7 @@ import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelDistribution;
import org.apache.calcite.rel.RelFieldCollation;
+import org.apache.calcite.rel.RelHomogeneousShuttle;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
@@ -1806,7 +1807,7 @@ public class RelBuilder {
*/
@Experimental
public RelBuilder transientScan(String tableName, RelDataType rowType) {
- ListTransientTable transientTable = new ListTransientTable(tableName, rowType);
+ TransientTable transientTable = new ListTransientTable(tableName, rowType);
RelOptTable relOptTable = RelOptTableImpl.create(
relOptSchema,
rowType,
@@ -1823,11 +1824,10 @@ public class RelBuilder {
*
* @param readType Spool's read type (as described in {@link Spool.Type})
* @param writeType Spool's write type (as described in {@link Spool.Type})
- * @param tableName Table name
+ * @param table Table to write into
*/
- private RelBuilder tableSpool(Spool.Type readType, Spool.Type writeType,
- String tableName) {
- RelNode spool = spoolFactory.createTableSpool(peek(), readType, writeType, tableName);
+ private RelBuilder tableSpool(Spool.Type readType, Spool.Type writeType, RelOptTable table) {
+ RelNode spool = spoolFactory.createTableSpool(peek(), readType, writeType, table);
replaceTop(spool);
return this;
}
@@ -1866,14 +1866,46 @@ public class RelBuilder {
* @param tableName Name of the {@link TransientTable} associated to the
* {@link RepeatUnion}
* @param all Whether duplicates are considered
- * @param maxRep Maximum number of iterations; -1 means no limit
+ * @param iterationLimit Maximum number of iterations; negative value means no limit
*/
@Experimental
- public RelBuilder repeatUnion(String tableName, boolean all, int maxRep) {
- RelNode iterative = tableSpool(Spool.Type.LAZY, Spool.Type.LAZY, tableName).build();
- RelNode seed = tableSpool(Spool.Type.LAZY, Spool.Type.LAZY, tableName).build();
- RelNode repeatUnion = repeatUnionFactory.createRepeatUnion(seed, iterative, all, maxRep);
- return push(repeatUnion);
+ public RelBuilder repeatUnion(String tableName, boolean all, int iterationLimit) {
+ RelOptTableFinder finder = new RelOptTableFinder(tableName);
+ for (int i = 0; i < stack.size(); i++) { // search scan(tableName) in the stack
+ peek(i).accept(finder);
+ if (finder.relOptTable != null) { // found
+ break;
+ }
+ }
+ if (finder.relOptTable == null) {
+ throw RESOURCE.tableNotFound(tableName).ex();
+ }
+
+ RelNode iterative = tableSpool(Spool.Type.LAZY, Spool.Type.LAZY, finder.relOptTable).build();
+ RelNode seed = tableSpool(Spool.Type.LAZY, Spool.Type.LAZY, finder.relOptTable).build();
+ RelNode repUnion = repeatUnionFactory.createRepeatUnion(seed, iterative, all, iterationLimit);
+ return push(repUnion);
+ }
+
+ /**
+ * Auxiliary class to find a certain RelOptTable based on its name
+ */
+ private static final class RelOptTableFinder extends RelHomogeneousShuttle {
+ private RelOptTable relOptTable = null;
+ private final String tableName;
+
+ private RelOptTableFinder(String tableName) {
+ this.tableName = tableName;
+ }
+
+ @Override public RelNode visit(TableScan scan) {
+ final RelOptTable scanTable = scan.getTable();
+ final List<String> qualifiedName = scanTable.getQualifiedName();
+ if (qualifiedName.get(qualifiedName.size() - 1).equals(tableName)) {
+ relOptTable = scanTable;
+ }
+ return super.visit(scan);
+ }
}
/** Creates a {@link Join}. */
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index 1f8f844..b7e38cc 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -1403,9 +1403,9 @@ public class RelBuilderTest {
.repeatUnion("DELTA_TABLE", true)
.build();
final String expected = "LogicalRepeatUnion(all=[true])\n"
- + " LogicalTableSpool(readType=[LAZY], writeType=[LAZY], tableName=[DELTA_TABLE])\n"
+ + " LogicalTableSpool(readType=[LAZY], writeType=[LAZY], table=[[DELTA_TABLE]])\n"
+ " LogicalValues(tuples=[[{ 1 }]])\n"
- + " LogicalTableSpool(readType=[LAZY], writeType=[LAZY], tableName=[DELTA_TABLE])\n"
+ + " LogicalTableSpool(readType=[LAZY], writeType=[LAZY], table=[[DELTA_TABLE]])\n"
+ " LogicalProject($f0=[+($0, 1)])\n"
+ " LogicalFilter(condition=[<($0, 10)])\n"
+ " LogicalTableScan(table=[[DELTA_TABLE]])\n";
@@ -1443,9 +1443,9 @@ public class RelBuilderTest {
.repeatUnion("AUX", true)
.build();
final String expected = "LogicalRepeatUnion(all=[true])\n"
- + " LogicalTableSpool(readType=[LAZY], writeType=[LAZY], tableName=[AUX])\n"
+ + " LogicalTableSpool(readType=[LAZY], writeType=[LAZY], table=[[AUX]])\n"
+ " LogicalValues(tuples=[[{ 0, 1 }]])\n"
- + " LogicalTableSpool(readType=[LAZY], writeType=[LAZY], tableName=[AUX])\n"
+ + " LogicalTableSpool(readType=[LAZY], writeType=[LAZY], table=[[AUX]])\n"
+ " LogicalProject(n=[+($0, 1)], fact=[*(+($0, 1), $1)])\n"
+ " LogicalFilter(condition=[<($0, 7)])\n"
+ " LogicalTableScan(table=[[AUX]])\n";
diff --git a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableRepeatUnionHierarchyTest.java b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableRepeatUnionHierarchyTest.java
index 50733e1..955a149 100644
--- a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableRepeatUnionHierarchyTest.java
+++ b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableRepeatUnionHierarchyTest.java
@@ -61,9 +61,9 @@ public class EnumerableRepeatUnionHierarchyTest {
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {
{ 1, true, -1, new String[]{EMP1} },
- { 2, true, -1, new String[]{EMP2, EMP1} },
+ { 2, true, -2, new String[]{EMP2, EMP1} },
{ 3, true, -1, new String[]{EMP3, EMP2, EMP1} },
- { 4, true, -1, new String[]{EMP4, EMP1} },
+ { 4, true, -5, new String[]{EMP4, EMP1} },
{ 5, true, -1, new String[]{EMP5, EMP2, EMP1} },
{ 3, true, 0, new String[]{EMP3} },
{ 3, true, 1, new String[]{EMP3, EMP2} },
@@ -71,8 +71,8 @@ public class EnumerableRepeatUnionHierarchyTest {
{ 3, true, 10, new String[]{EMP3, EMP2, EMP1} },
{ 1, false, -1, new String[]{EMP1, EMP2, EMP4, EMP3, EMP5} },
- { 2, false, -1, new String[]{EMP2, EMP3, EMP5} },
- { 3, false, -1, new String[]{EMP3} },
+ { 2, false, -10, new String[]{EMP2, EMP3, EMP5} },
+ { 3, false, -100, new String[]{EMP3} },
{ 4, false, -1, new String[]{EMP4} },
{ 1, false, 0, new String[]{EMP1} },
{ 1, false, 1, new String[]{EMP1, EMP2, EMP4} },
diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java b/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
index 2f2683c..459a564 100644
--- a/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
+++ b/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
@@ -3379,21 +3379,21 @@ public abstract class EnumerableDefaults {
* no results, or an optional maximum numbers of iterations is reached
* @param seed seed enumerable
* @param iteration iteration enumerable
- * @param maxRep maximum numbers of repetitions for the iteration enumerable (-1 means no limit)
+ * @param iterationLimit maximum numbers of repetitions for the iteration enumerable
+ * (negative value means no limit)
* @param <TSource> record type
*/
@SuppressWarnings("unchecked")
public static <TSource> Enumerable<TSource> repeatUnionAll(
Enumerable<TSource> seed,
Enumerable<TSource> iteration,
- int maxRep) {
- assert maxRep >= -1;
+ int iterationLimit) {
return new AbstractEnumerable<TSource>() {
@Override public Enumerator<TSource> enumerator() {
return new Enumerator<TSource>() {
private TSource current = (TSource) DUMMY;
private boolean seedProcessed = false;
- private int currentRep = 0;
+ private int currentIteration = 0;
private final Enumerator<TSource> seedEnumerator = seed.enumerator();
private Enumerator<TSource> iterativeEnumerator = null;
@@ -3417,7 +3417,7 @@ public abstract class EnumerableDefaults {
// if we are done with the seed, moveNext on the iterative part
while (true) {
- if (maxRep != -1 && this.currentRep == maxRep) {
+ if (iterationLimit >= 0 && this.currentIteration == iterationLimit) {
// max number of iterations reached, we are done
this.current = (TSource) DUMMY;
return false;
@@ -3441,7 +3441,7 @@ public abstract class EnumerableDefaults {
this.current = (TSource) DUMMY;
this.iterativeEnumerator.close();
this.iterativeEnumerator = null;
- this.currentRep++;
+ this.currentIteration++;
}
}
@@ -3451,14 +3451,13 @@ public abstract class EnumerableDefaults {
this.iterativeEnumerator.close();
this.iterativeEnumerator = null;
}
- this.currentRep = 0;
+ this.currentIteration = 0;
}
@Override public void close() {
this.seedEnumerator.close();
if (this.iterativeEnumerator != null) {
this.iterativeEnumerator.close();
- this.iterativeEnumerator = null;
}
}
};