use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.type.RelDataType in project calcite by apache.
the class LoptOptimizeJoinRule method createReplacementJoin.
/**
* Creates a replacement join, projecting either dummy columns or
* replacement keys from the factor that doesn't actually need to be joined.
*
* @param multiJoin join factors being optimized
* @param semiJoinOpt optimal semijoins for each factor
* @param currJoinTree current join tree being added to
* @param leftIdx if ≥ 0, when creating the replacement join, only consider
* filters that reference leftIdx in currJoinTree; otherwise, consider all
* filters that reference any factor in currJoinTree
* @param factorToAdd new factor whose join can be removed
* @param newKeys join keys that need to be replaced
* @param replacementKeys the keys that replace the join keys; null if we're
* removing the null generating factor in an outer join
* @param filtersToAdd filters remaining to be added; filters added to the
* new join tree are removed from the list
*
* @return created join tree with an appropriate projection for the factor
* that can be removed
*/
private LoptJoinTree createReplacementJoin(RelBuilder relBuilder, LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree currJoinTree, int leftIdx, int factorToAdd, ImmutableIntList newKeys, Integer[] replacementKeys, List<RexNode> filtersToAdd) {
// create a projection, projecting the fields from the join tree
// containing the current joinRel and the new factor; for fields
// corresponding to join keys, replace them with the corresponding key
// from the replacementKeys passed in; for other fields, just create a
// null expression as a placeholder for the column; this is done so we
// don't have to adjust the offsets of other expressions that reference
// the new factor; the placeholder expression values should never be
// referenced, so that's why it's ok to create these possibly invalid
// expressions
RelNode currJoinRel = currJoinTree.getJoinTree();
List<RelDataTypeField> currFields = currJoinRel.getRowType().getFieldList();
final int nCurrFields = currFields.size();
List<RelDataTypeField> newFields = multiJoin.getJoinFactor(factorToAdd).getRowType().getFieldList();
final int nNewFields = newFields.size();
List<Pair<RexNode, String>> projects = Lists.newArrayList();
RexBuilder rexBuilder = currJoinRel.getCluster().getRexBuilder();
RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
for (int i = 0; i < nCurrFields; i++) {
projects.add(Pair.of((RexNode) rexBuilder.makeInputRef(currFields.get(i).getType(), i), currFields.get(i).getName()));
}
for (int i = 0; i < nNewFields; i++) {
RexNode projExpr;
RelDataType newType = newFields.get(i).getType();
if (!newKeys.contains(i)) {
if (replacementKeys == null) {
// null generating factor in an outer join; so make the
// type nullable
newType = typeFactory.createTypeWithNullability(newType, true);
}
projExpr = rexBuilder.makeCast(newType, rexBuilder.constantNull());
} else {
RelDataTypeField mappedField = currFields.get(replacementKeys[i]);
RexNode mappedInput = rexBuilder.makeInputRef(mappedField.getType(), replacementKeys[i]);
// if the types aren't the same, create a cast
if (mappedField.getType() == newType) {
projExpr = mappedInput;
} else {
projExpr = rexBuilder.makeCast(newFields.get(i).getType(), mappedInput);
}
}
projects.add(Pair.of(projExpr, newFields.get(i).getName()));
}
relBuilder.push(currJoinRel);
relBuilder.project(Pair.left(projects), Pair.right(projects));
// remove the join conditions corresponding to the join we're removing;
// we don't actually need to use them, but we need to remove them
// from the list since they're no longer needed
LoptJoinTree newTree = new LoptJoinTree(semiJoinOpt.getChosenSemiJoin(factorToAdd), factorToAdd);
addFilters(multiJoin, currJoinTree, leftIdx, newTree, filtersToAdd, false);
// LogicalFilter placed on top off the projection created above.
if (leftIdx >= 0) {
addAdditionalFilters(relBuilder, multiJoin, currJoinTree, newTree, filtersToAdd);
}
// from the new factor as we go up in the join tree
return new LoptJoinTree(relBuilder.build(), currJoinTree.getFactorTree(), newTree.getFactorTree());
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.type.RelDataType 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.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.type.RelDataType in project calcite by apache.
the class JoinProjectTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
Join joinRel = call.rel(0);
JoinRelType joinType = joinRel.getJoinType();
Project leftProj;
Project rightProj;
RelNode leftJoinChild;
RelNode rightJoinChild;
// 2) input's projection doesn't generate nulls
if (hasLeftChild(call) && (includeOuter || !joinType.generatesNullsOnLeft())) {
leftProj = call.rel(1);
leftJoinChild = getProjectChild(call, leftProj, true);
} else {
leftProj = null;
leftJoinChild = call.rel(1);
}
if (hasRightChild(call) && (includeOuter || !joinType.generatesNullsOnRight())) {
rightProj = getRightChild(call);
rightJoinChild = getProjectChild(call, rightProj, false);
} else {
rightProj = null;
rightJoinChild = joinRel.getRight();
}
if ((leftProj == null) && (rightProj == null)) {
return;
}
// Construct two RexPrograms and combine them. The bottom program
// is a join of the projection expressions from the left and/or
// right projects that feed into the join. The top program contains
// the join condition.
// Create a row type representing a concatenation of the inputs
// underneath the projects that feed into the join. This is the input
// into the bottom RexProgram. Note that the join type is an inner
// join because the inputs haven't actually been joined yet.
RelDataType joinChildrenRowType = SqlValidatorUtil.deriveJoinRowType(leftJoinChild.getRowType(), rightJoinChild.getRowType(), JoinRelType.INNER, joinRel.getCluster().getTypeFactory(), null, Collections.<RelDataTypeField>emptyList());
// Create projection expressions, combining the projection expressions
// from the projects that feed into the join. For the RHS projection
// expressions, shift them to the right by the number of fields on
// the LHS. If the join input was not a projection, simply create
// references to the inputs.
int nProjExprs = joinRel.getRowType().getFieldCount();
final List<Pair<RexNode, String>> projects = new ArrayList<>();
final RexBuilder rexBuilder = joinRel.getCluster().getRexBuilder();
createProjectExprs(leftProj, leftJoinChild, 0, rexBuilder, joinChildrenRowType.getFieldList(), projects);
List<RelDataTypeField> leftFields = leftJoinChild.getRowType().getFieldList();
int nFieldsLeft = leftFields.size();
createProjectExprs(rightProj, rightJoinChild, nFieldsLeft, rexBuilder, joinChildrenRowType.getFieldList(), projects);
final List<RelDataType> projTypes = new ArrayList<>();
for (int i = 0; i < nProjExprs; i++) {
projTypes.add(projects.get(i).left.getType());
}
RelDataType projRowType = rexBuilder.getTypeFactory().createStructType(projTypes, Pair.right(projects));
// create the RexPrograms and merge them
RexProgram bottomProgram = RexProgram.create(joinChildrenRowType, Pair.left(projects), null, projRowType, rexBuilder);
RexProgramBuilder topProgramBuilder = new RexProgramBuilder(projRowType, rexBuilder);
topProgramBuilder.addIdentity();
topProgramBuilder.addCondition(joinRel.getCondition());
RexProgram topProgram = topProgramBuilder.getProgram();
RexProgram mergedProgram = RexProgramBuilder.mergePrograms(topProgram, bottomProgram, rexBuilder);
// expand out the join condition and construct a new LogicalJoin that
// directly references the join children without the intervening
// ProjectRels
RexNode newCondition = mergedProgram.expandLocalRef(mergedProgram.getCondition());
Join newJoinRel = joinRel.copy(joinRel.getTraitSet(), newCondition, leftJoinChild, rightJoinChild, joinRel.getJoinType(), joinRel.isSemiJoinDone());
// expand out the new projection expressions; if the join is an
// outer join, modify the expressions to reference the join output
final List<RexNode> newProjExprs = new ArrayList<>();
List<RexLocalRef> projList = mergedProgram.getProjectList();
List<RelDataTypeField> newJoinFields = newJoinRel.getRowType().getFieldList();
int nJoinFields = newJoinFields.size();
int[] adjustments = new int[nJoinFields];
for (int i = 0; i < nProjExprs; i++) {
RexNode newExpr = mergedProgram.expandLocalRef(projList.get(i));
if (joinType != JoinRelType.INNER) {
newExpr = newExpr.accept(new RelOptUtil.RexInputConverter(rexBuilder, joinChildrenRowType.getFieldList(), newJoinFields, adjustments));
}
newProjExprs.add(newExpr);
}
// finally, create the projection on top of the join
final RelBuilder relBuilder = call.builder();
relBuilder.push(newJoinRel);
relBuilder.project(newProjExprs, joinRel.getRowType().getFieldNames());
// projection to fix differences wrt nullability of fields
if (joinType != JoinRelType.INNER) {
relBuilder.convert(joinRel.getRowType(), false);
}
call.transformTo(relBuilder.build());
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.type.RelDataType in project calcite by apache.
the class RelToSqlConverter method visit.
/**
* @see #dispatch
*/
public Result visit(Values e) {
final List<Clause> clauses = ImmutableList.of(Clause.SELECT);
final Map<String, RelDataType> pairs = ImmutableMap.of();
final Context context = aliasContext(pairs, false);
SqlNode query;
final boolean rename = stack.size() <= 1 || !(Iterables.get(stack, 1).r instanceof TableModify);
final List<String> fieldNames = e.getRowType().getFieldNames();
if (!dialect.supportsAliasedValues() && rename) {
// Oracle does not support "AS t (c1, c2)". So instead of
// (VALUES (v0, v1), (v2, v3)) AS t (c0, c1)
// we generate
// SELECT v0 AS c0, v1 AS c1 FROM DUAL
// UNION ALL
// SELECT v2 AS c0, v3 AS c1 FROM DUAL
List<SqlSelect> list = new ArrayList<>();
for (List<RexLiteral> tuple : e.getTuples()) {
final List<SqlNode> values2 = new ArrayList<>();
final SqlNodeList exprList = exprList(context, tuple);
for (Pair<SqlNode, String> value : Pair.zip(exprList, fieldNames)) {
values2.add(SqlStdOperatorTable.AS.createCall(POS, value.left, new SqlIdentifier(value.right, POS)));
}
list.add(new SqlSelect(POS, null, new SqlNodeList(values2, POS), new SqlIdentifier("DUAL", POS), null, null, null, null, null, null, null));
}
if (list.size() == 1) {
query = list.get(0);
} else {
query = SqlStdOperatorTable.UNION_ALL.createCall(new SqlNodeList(list, POS));
}
} else {
// Generate ANSI syntax
// (VALUES (v0, v1), (v2, v3))
// or, if rename is required
// (VALUES (v0, v1), (v2, v3)) AS t (c0, c1)
final SqlNodeList selects = new SqlNodeList(POS);
for (List<RexLiteral> tuple : e.getTuples()) {
selects.add(ANONYMOUS_ROW.createCall(exprList(context, tuple)));
}
query = SqlStdOperatorTable.VALUES.createCall(selects);
if (rename) {
final List<SqlNode> list = new ArrayList<>();
list.add(query);
list.add(new SqlIdentifier("t", POS));
for (String fieldName : fieldNames) {
list.add(new SqlIdentifier(fieldName, POS));
}
query = SqlStdOperatorTable.AS.createCall(POS, list);
}
}
return result(query, clauses, e, null);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.type.RelDataType in project calcite by apache.
the class RelToSqlConverter method visit.
/**
* @see #dispatch
*/
public Result visit(TableModify modify) {
final Map<String, RelDataType> pairs = ImmutableMap.of();
final Context context = aliasContext(pairs, false);
// Target Table Name
final SqlIdentifier sqlTargetTable = new SqlIdentifier(modify.getTable().getQualifiedName(), POS);
switch(modify.getOperation()) {
case INSERT:
{
// Convert the input to a SELECT query or keep as VALUES. Not all
// dialects support naked VALUES, but all support VALUES inside INSERT.
final SqlNode sqlSource = visitChild(0, modify.getInput()).asQueryOrValues();
final SqlInsert sqlInsert = new SqlInsert(POS, SqlNodeList.EMPTY, sqlTargetTable, sqlSource, identifierList(modify.getInput().getRowType().getFieldNames()));
return result(sqlInsert, ImmutableList.<Clause>of(), modify, null);
}
case UPDATE:
{
final Result input = visitChild(0, modify.getInput());
final SqlUpdate sqlUpdate = new SqlUpdate(POS, sqlTargetTable, identifierList(modify.getUpdateColumnList()), exprList(context, modify.getSourceExpressionList()), ((SqlSelect) input.node).getWhere(), input.asSelect(), null);
return result(sqlUpdate, input.clauses, modify, null);
}
case DELETE:
{
final Result input = visitChild(0, modify.getInput());
final SqlDelete sqlDelete = new SqlDelete(POS, sqlTargetTable, input.asSelect().getWhere(), input.asSelect(), null);
return result(sqlDelete, input.clauses, modify, null);
}
case MERGE:
default:
throw new AssertionError("not implemented: " + modify);
}
}
Aggregations