use of org.apache.calcite.plan.RelOptLattice in project calcite by apache.
the class AggregateStarTableRule method apply.
protected void apply(RelOptRuleCall call, Project postProject, final Aggregate aggregate, StarTable.StarTableScan scan) {
final RelOptCluster cluster = scan.getCluster();
final RelOptTable table = scan.getTable();
final RelOptLattice lattice = call.getPlanner().getLattice(table);
final List<Lattice.Measure> measures = lattice.lattice.toMeasures(aggregate.getAggCallList());
final Pair<CalciteSchema.TableEntry, TileKey> pair = lattice.getAggregate(call.getPlanner(), aggregate.getGroupSet(), measures);
if (pair == null) {
return;
}
final RelBuilder relBuilder = call.builder();
final CalciteSchema.TableEntry tableEntry = pair.left;
final TileKey tileKey = pair.right;
final RelMetadataQuery mq = call.getMetadataQuery();
final double rowCount = aggregate.estimateRowCount(mq);
final Table aggregateTable = tableEntry.getTable();
final RelDataType aggregateTableRowType = aggregateTable.getRowType(cluster.getTypeFactory());
final RelOptTable aggregateRelOptTable = RelOptTableImpl.create(table.getRelOptSchema(), aggregateTableRowType, tableEntry, rowCount);
relBuilder.push(aggregateRelOptTable.toRel(RelOptUtil.getContext(cluster)));
if (tileKey == null) {
if (CalcitePrepareImpl.DEBUG) {
System.out.println("Using materialization " + aggregateRelOptTable.getQualifiedName() + " (exact match)");
}
} else if (!tileKey.dimensions.equals(aggregate.getGroupSet())) {
// Aggregate has finer granularity than we need. Roll up.
if (CalcitePrepareImpl.DEBUG) {
System.out.println("Using materialization " + aggregateRelOptTable.getQualifiedName() + ", rolling up " + tileKey.dimensions + " to " + aggregate.getGroupSet());
}
assert tileKey.dimensions.contains(aggregate.getGroupSet());
final List<AggregateCall> aggCalls = Lists.newArrayList();
ImmutableBitSet.Builder groupSet = ImmutableBitSet.builder();
for (int key : aggregate.getGroupSet()) {
groupSet.set(tileKey.dimensions.indexOf(key));
}
for (AggregateCall aggCall : aggregate.getAggCallList()) {
final AggregateCall copy = rollUp(groupSet.cardinality(), relBuilder, aggCall, tileKey);
if (copy == null) {
return;
}
aggCalls.add(copy);
}
relBuilder.push(aggregate.copy(aggregate.getTraitSet(), relBuilder.build(), false, groupSet.build(), null, aggCalls));
} else if (!tileKey.measures.equals(measures)) {
if (CalcitePrepareImpl.DEBUG) {
System.out.println("Using materialization " + aggregateRelOptTable.getQualifiedName() + ", right granularity, but different measures " + aggregate.getAggCallList());
}
relBuilder.project(relBuilder.fields(new AbstractSourceMapping(tileKey.dimensions.cardinality() + tileKey.measures.size(), aggregate.getRowType().getFieldCount()) {
public int getSourceOpt(int source) {
assert aggregate.getIndicatorCount() == 0;
if (source < aggregate.getGroupCount()) {
int in = tileKey.dimensions.nth(source);
return aggregate.getGroupSet().indexOf(in);
}
Lattice.Measure measure = measures.get(source - aggregate.getGroupCount());
int i = tileKey.measures.indexOf(measure);
assert i >= 0;
return tileKey.dimensions.cardinality() + i;
}
}.inverse()));
}
if (postProject != null) {
relBuilder.push(postProject.copy(postProject.getTraitSet(), ImmutableList.of(relBuilder.peek())));
}
call.transformTo(relBuilder.build());
}
use of org.apache.calcite.plan.RelOptLattice in project calcite by apache.
the class Prepare method optimize.
/**
* Optimizes a query plan.
*
* @param root Root of relational expression tree
* @param materializations Tables known to be populated with a given query
* @param lattices Lattices
* @return an equivalent optimized relational expression
*/
protected RelRoot optimize(RelRoot root, final List<Materialization> materializations, final List<CalciteSchema.LatticeEntry> lattices) {
final RelOptPlanner planner = root.rel.getCluster().getPlanner();
final DataContext dataContext = context.getDataContext();
planner.setExecutor(new RexExecutorImpl(dataContext));
final List<RelOptMaterialization> materializationList = new ArrayList<>();
for (Materialization materialization : materializations) {
List<String> qualifiedTableName = materialization.materializedTable.path();
materializationList.add(new RelOptMaterialization(materialization.tableRel, materialization.queryRel, materialization.starRelOptTable, qualifiedTableName));
}
final List<RelOptLattice> latticeList = new ArrayList<>();
for (CalciteSchema.LatticeEntry lattice : lattices) {
final CalciteSchema.TableEntry starTable = lattice.getStarTable();
final JavaTypeFactory typeFactory = context.getTypeFactory();
final RelOptTableImpl starRelOptTable = RelOptTableImpl.create(catalogReader, starTable.getTable().getRowType(typeFactory), starTable, null);
latticeList.add(new RelOptLattice(lattice.getLattice(), starRelOptTable));
}
final RelTraitSet desiredTraits = getDesiredRootTraitSet(root);
// Work around
// [CALCITE-1774] Allow rules to be registered during planning process
// by briefly creating each kind of physical table to let it register its
// rules. The problem occurs when plans are created via RelBuilder, not
// the usual process (SQL and SqlToRelConverter.Config.isConvertTableAccess
// = true).
final RelVisitor visitor = new RelVisitor() {
@Override
public void visit(RelNode node, int ordinal, RelNode parent) {
if (node instanceof TableScan) {
final RelOptCluster cluster = node.getCluster();
final RelOptTable.ToRelContext context = RelOptUtil.getContext(cluster);
final RelNode r = node.getTable().toRel(context);
planner.registerClass(r);
}
super.visit(node, ordinal, parent);
}
};
visitor.go(root.rel);
final Program program = getProgram();
final RelNode rootRel4 = program.run(planner, root.rel, desiredTraits, materializationList, latticeList);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Plan after physical tweaks: {}", RelOptUtil.toString(rootRel4, SqlExplainLevel.ALL_ATTRIBUTES));
}
return root.withRel(rootRel4);
}
use of org.apache.calcite.plan.RelOptLattice in project calcite by apache.
the class Programs method standard.
/**
* Returns the standard program with user metadata provider.
*/
public static Program standard(RelMetadataProvider metadataProvider) {
final Program program1 = new Program() {
public RelNode run(RelOptPlanner planner, RelNode rel, RelTraitSet requiredOutputTraits, List<RelOptMaterialization> materializations, List<RelOptLattice> lattices) {
planner.setRoot(rel);
for (RelOptMaterialization materialization : materializations) {
planner.addMaterialization(materialization);
}
for (RelOptLattice lattice : lattices) {
planner.addLattice(lattice);
}
final RelNode rootRel2 = rel.getTraitSet().equals(requiredOutputTraits) ? rel : planner.changeTraits(rel, requiredOutputTraits);
assert rootRel2 != null;
planner.setRoot(rootRel2);
final RelOptPlanner planner2 = planner.chooseDelegate();
final RelNode rootRel3 = planner2.findBestExp();
assert rootRel3 != null : "could not implement exp";
return rootRel3;
}
};
return sequence(subQuery(metadataProvider), new DecorrelateProgram(), new TrimFieldsProgram(), program1, // EnumerableCalcRel is introduced.
calc(metadataProvider));
}
Aggregations