Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions core/src/main/java/org/apache/calcite/tools/Programs.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.calcite.config.CalciteSystemProperty;
import org.apache.calcite.plan.RelOptCostImpl;
import org.apache.calcite.plan.RelOptLattice;
import org.apache.calcite.plan.RelOptListener;
import org.apache.calcite.plan.RelOptMaterialization;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelOptRule;
Expand Down Expand Up @@ -53,6 +54,8 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;

import org.checkerframework.checker.nullness.qual.Nullable;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
Expand Down Expand Up @@ -190,6 +193,41 @@ public static Program of(final HepProgram hepProgram, final boolean noDag,
return hepPlanner.findBestExp();
};
}
/** Creates a program that executes a {@link HepProgram}.
*
* <p>If {@code listener} is not null, it is
* {@linkplain HepPlanner#addListener(RelOptListener) attached}
* to the planner before execution. */
@SuppressWarnings("deprecation")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this be done without calling deprecated functions?

public static Program of(final HepProgram hepProgram, final boolean noDag,
final RelMetadataProvider metadataProvider,
final @Nullable RelOptListener listener) {
requireNonNull(metadataProvider, "metadataProvider");
if (listener == null) {
return of(hepProgram, noDag, metadataProvider);
}
return (planner, rel, requiredOutputTraits, materializations, lattices) -> {
final HepPlanner hepPlanner =
new HepPlanner(hepProgram, null, noDag, null, RelOptCostImpl.FACTORY);

hepPlanner.addListener(listener);

List<RelMetadataProvider> list = Lists.newArrayList(metadataProvider);
hepPlanner.registerMetadataProviders(list);
for (RelOptMaterialization materialization : materializations) {
hepPlanner.addMaterialization(materialization);
}
for (RelOptLattice lattice : lattices) {
hepPlanner.addLattice(lattice);
}
RelMetadataProvider plannerChain =
ChainedRelMetadataProvider.of(list);
rel.getCluster().setMetadataProvider(plannerChain);

hepPlanner.setRoot(rel);
return hepPlanner.findBestExp();
};
}

/** Creates a program that invokes heuristic join-order optimization
* (via {@link org.apache.calcite.rel.rules.JoinToMultiJoinRule},
Expand Down
52 changes: 52 additions & 0 deletions core/src/test/java/org/apache/calcite/test/HepPlannerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@
import org.apache.calcite.rel.logical.LogicalIntersect;
import org.apache.calcite.rel.logical.LogicalUnion;
import org.apache.calcite.rel.logical.LogicalValues;
import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataProvider;
import org.apache.calcite.rel.rules.CoerceInputsRule;
import org.apache.calcite.rel.rules.CoreRules;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.tools.Program;
import org.apache.calcite.tools.Programs;
import org.apache.calcite.tools.RelBuilder;

import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -563,4 +567,52 @@ long getApplyTimes() {
final RelNode result = planner.findBestExp();
assertThat(result, is(instanceOf(LogicalValues.class)));
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-7549">[CALCITE-7549]
* Add Programs.of overload accepting RelOptListener</a>.
*
* <p>Verifies that a {@link RelOptListener} passed to
* {@link Programs#of(HepProgram, boolean, RelMetadataProvider, RelOptListener)}
* receives rule-attempted events during execution. */
@Test void testProgramsOfWithListener() {
final HepTestListener listener = new HepTestListener(0);

final HepProgram program = new HepProgramBuilder()
.addRuleInstance(CoreRules.FILTER_TO_CALC)
.build();

final Program p =
Programs.of(program, true, DefaultRelMetadataProvider.INSTANCE, listener);

final String sql = "select 1 from dept where abs(-1) = 20";
final RelNode rel = sql(sql).toRel();

final RelNode result =
p.run(rel.getCluster().getPlanner(), rel, rel.getTraitSet(),
ImmutableList.of(), ImmutableList.of());

// The listener must have been notified at least once
assertThat(listener.getApplyTimes() > 0, is(true));
}

/** Tests that {@link Programs#of(HepProgram, boolean, RelMetadataProvider, RelOptListener)}
* with a null listener behaves identically to the overload without a listener. */
@Test void testProgramsOfWithNullListener() {
final HepProgram program = new HepProgramBuilder()
.addRuleInstance(CoreRules.FILTER_TO_CALC)
.build();

final Program p =
Programs.of(program, true, DefaultRelMetadataProvider.INSTANCE, null);

final String sql = "select 1 from dept where abs(-1) = 20";
final RelNode rel = sql(sql).toRel();

// Should not throw; null listener is safely ignored
final RelNode result =
p.run(rel.getCluster().getPlanner(), rel, rel.getTraitSet(),
ImmutableList.of(), ImmutableList.of());
assertThat(result, is(notNullValue()));
}
}
10 changes: 10 additions & 0 deletions core/src/test/resources/org/apache/calcite/test/HepPlannerTest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,16 @@ LogicalAggregate(group=[{0}])
<![CDATA[select name from sales.dept]]>
</Resource>
</TestCase>
<TestCase name="testProgramsOfWithListener">
<Resource name="sql">
<![CDATA[select 1 from dept where abs(-1) = 20]]>
</Resource>
</TestCase>
<TestCase name="testProgramsOfWithNullListener">
<Resource name="sql">
<![CDATA[select 1 from dept where abs(-1) = 20]]>
</Resource>
</TestCase>
<TestCase name="testRelDigestLength">
<Resource name="sql">
<![CDATA[select * from (select name from sales.dept union all select name from sales.dept union all select name from sales.dept union all select name from sales.dept union all select name from sales.dept union all select name from sales.dept union all select name from sales.dept union all select name from sales.dept union all select name from sales.dept union all select name from sales.dept union all select name from sales.dept)]]>
Expand Down