use of org.apache.calcite.schema.impl.StarTable in project calcite by apache.
the class CalciteMaterializer method useStar.
/**
* Converts a relational expression to use a
* {@link org.apache.calcite.schema.impl.StarTable} defined in {@code schema}.
* Uses the first star table that fits.
*/
private Iterable<Callback> useStar(CalciteSchema schema, RelNode queryRel) {
List<CalciteSchema.TableEntry> starTables = Schemas.getStarTables(schema.root());
if (starTables.isEmpty()) {
// Don't waste effort converting to leaf-join form.
return ImmutableList.of();
}
final List<Callback> list = Lists.newArrayList();
final RelNode rel2 = RelOptMaterialization.toLeafJoinForm(queryRel);
for (CalciteSchema.TableEntry starTable : starTables) {
final Table table = starTable.getTable();
assert table instanceof StarTable;
RelOptTableImpl starRelOptTable = RelOptTableImpl.create(catalogReader, table.getRowType(typeFactory), starTable, null);
final RelNode rel3 = RelOptMaterialization.tryUseStar(rel2, starRelOptTable);
if (rel3 != null) {
list.add(new Callback(rel3, starTable, starRelOptTable));
}
}
return list;
}
use of org.apache.calcite.schema.impl.StarTable in project calcite by apache.
the class RelOptMaterialization method tryUseStar.
/**
* Converts a relational expression to one that uses a
* {@link org.apache.calcite.schema.impl.StarTable}.
*
* <p>The relational expression is already in leaf-join-form, per
* {@link #toLeafJoinForm(org.apache.calcite.rel.RelNode)}.
*
* @return Rewritten expression, or null if expression cannot be rewritten
* to use the star
*/
public static RelNode tryUseStar(RelNode rel, final RelOptTable starRelOptTable) {
final StarTable starTable = starRelOptTable.unwrap(StarTable.class);
assert starTable != null;
RelNode rel2 = rel.accept(new RelShuttleImpl() {
@Override
public RelNode visit(TableScan scan) {
RelOptTable relOptTable = scan.getTable();
final Table table = relOptTable.unwrap(Table.class);
if (table.equals(starTable.tables.get(0))) {
Mappings.TargetMapping mapping = Mappings.createShiftMapping(starRelOptTable.getRowType().getFieldCount(), 0, 0, relOptTable.getRowType().getFieldCount());
final RelOptCluster cluster = scan.getCluster();
final RelNode scan2 = starRelOptTable.toRel(RelOptUtil.getContext(cluster));
return RelOptUtil.createProject(scan2, Mappings.asList(mapping.inverse()));
}
return scan;
}
@Override
public RelNode visit(LogicalJoin join) {
for (; ; ) {
RelNode rel = super.visit(join);
if (rel == join || !(rel instanceof LogicalJoin)) {
return rel;
}
join = (LogicalJoin) rel;
final ProjectFilterTable left = ProjectFilterTable.of(join.getLeft());
if (left != null) {
final ProjectFilterTable right = ProjectFilterTable.of(join.getRight());
if (right != null) {
try {
match(left, right, join.getCluster());
} catch (Util.FoundOne e) {
return (RelNode) e.getNode();
}
}
}
}
}
/**
* Throws a {@link org.apache.calcite.util.Util.FoundOne} containing
* a {@link org.apache.calcite.rel.logical.LogicalTableScan} on
* success. (Yes, an exception for normal operation.)
*/
private void match(ProjectFilterTable left, ProjectFilterTable right, RelOptCluster cluster) {
final Mappings.TargetMapping leftMapping = left.mapping();
final Mappings.TargetMapping rightMapping = right.mapping();
final RelOptTable leftRelOptTable = left.getTable();
final Table leftTable = leftRelOptTable.unwrap(Table.class);
final int leftCount = leftRelOptTable.getRowType().getFieldCount();
final RelOptTable rightRelOptTable = right.getTable();
final Table rightTable = rightRelOptTable.unwrap(Table.class);
if (leftTable instanceof StarTable && ((StarTable) leftTable).tables.contains(rightTable)) {
final int offset = ((StarTable) leftTable).columnOffset(rightTable);
Mappings.TargetMapping mapping = Mappings.merge(leftMapping, Mappings.offsetTarget(Mappings.offsetSource(rightMapping, offset), leftMapping.getTargetCount()));
final RelNode project = RelOptUtil.createProject(LogicalTableScan.create(cluster, leftRelOptTable), Mappings.asList(mapping.inverse()));
final List<RexNode> conditions = Lists.newArrayList();
if (left.condition != null) {
conditions.add(left.condition);
}
if (right.condition != null) {
conditions.add(RexUtil.apply(mapping, RexUtil.shift(right.condition, offset)));
}
final RelNode filter = RelOptUtil.createFilter(project, conditions);
throw new Util.FoundOne(filter);
}
if (rightTable instanceof StarTable && ((StarTable) rightTable).tables.contains(leftTable)) {
final int offset = ((StarTable) rightTable).columnOffset(leftTable);
Mappings.TargetMapping mapping = Mappings.merge(Mappings.offsetSource(leftMapping, offset), Mappings.offsetTarget(rightMapping, leftCount));
final RelNode project = RelOptUtil.createProject(LogicalTableScan.create(cluster, rightRelOptTable), Mappings.asList(mapping.inverse()));
final List<RexNode> conditions = Lists.newArrayList();
if (left.condition != null) {
conditions.add(RexUtil.apply(mapping, RexUtil.shift(left.condition, offset)));
}
if (right.condition != null) {
conditions.add(RexUtil.apply(mapping, right.condition));
}
final RelNode filter = RelOptUtil.createFilter(project, conditions);
throw new Util.FoundOne(filter);
}
}
});
if (rel2 == rel) {
// No rewrite happened.
return null;
}
final Program program = Programs.hep(ImmutableList.of(ProjectFilterTransposeRule.INSTANCE, AggregateProjectMergeRule.INSTANCE, AggregateFilterTransposeRule.INSTANCE), false, DefaultRelMetadataProvider.INSTANCE);
return program.run(null, rel2, null, ImmutableList.<RelOptMaterialization>of(), ImmutableList.<RelOptLattice>of());
}
Aggregations