Search in sources :

Example 76 with RelDataType

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());
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RexBuilder(org.apache.calcite.rex.RexBuilder) RelDataType(org.apache.calcite.rel.type.RelDataType) IntPair(org.apache.calcite.util.mapping.IntPair) Pair(org.apache.calcite.util.Pair) RexNode(org.apache.calcite.rex.RexNode)

Example 77 with RelDataType

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());
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) RelBuilder(org.apache.calcite.tools.RelBuilder) RelOptTable(org.apache.calcite.plan.RelOptTable) Table(org.apache.calcite.schema.Table) StarTable(org.apache.calcite.schema.impl.StarTable) RelBuilder(org.apache.calcite.tools.RelBuilder) TileKey(org.apache.calcite.materialize.TileKey) RelDataType(org.apache.calcite.rel.type.RelDataType) AggregateCall(org.apache.calcite.rel.core.AggregateCall) AbstractSourceMapping(org.apache.calcite.util.mapping.AbstractSourceMapping) CalciteSchema(org.apache.calcite.jdbc.CalciteSchema) RelOptLattice(org.apache.calcite.plan.RelOptLattice) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) RelOptTable(org.apache.calcite.plan.RelOptTable)

Example 78 with RelDataType

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());
}
Also used : RelBuilder(org.apache.calcite.tools.RelBuilder) RexProgram(org.apache.calcite.rex.RexProgram) ArrayList(java.util.ArrayList) Join(org.apache.calcite.rel.core.Join) LogicalJoin(org.apache.calcite.rel.logical.LogicalJoin) RelDataType(org.apache.calcite.rel.type.RelDataType) JoinRelType(org.apache.calcite.rel.core.JoinRelType) Project(org.apache.calcite.rel.core.Project) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexBuilder(org.apache.calcite.rex.RexBuilder) RexLocalRef(org.apache.calcite.rex.RexLocalRef) RexProgramBuilder(org.apache.calcite.rex.RexProgramBuilder) Pair(org.apache.calcite.util.Pair) RexNode(org.apache.calcite.rex.RexNode)

Example 79 with RelDataType

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);
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlNodeList(org.apache.calcite.sql.SqlNodeList) TableModify(org.apache.calcite.rel.core.TableModify) SqlNode(org.apache.calcite.sql.SqlNode)

Example 80 with RelDataType

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);
    }
}
Also used : RelDataType(org.apache.calcite.rel.type.RelDataType) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlInsert(org.apache.calcite.sql.SqlInsert) SqlUpdate(org.apache.calcite.sql.SqlUpdate) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlDelete(org.apache.calcite.sql.SqlDelete) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

RelDataType (org.apache.calcite.rel.type.RelDataType)834 RexNode (org.apache.calcite.rex.RexNode)268 ArrayList (java.util.ArrayList)214 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)209 RelNode (org.apache.calcite.rel.RelNode)153 SqlNode (org.apache.calcite.sql.SqlNode)143 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)123 RexBuilder (org.apache.calcite.rex.RexBuilder)118 Test (org.junit.Test)62 ImmutableList (com.google.common.collect.ImmutableList)58 RexInputRef (org.apache.calcite.rex.RexInputRef)57 List (java.util.List)51 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)45 RexLiteral (org.apache.calcite.rex.RexLiteral)44 SqlNodeList (org.apache.calcite.sql.SqlNodeList)42 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)40 AggregateCall (org.apache.calcite.rel.core.AggregateCall)39 BitString (org.apache.calcite.util.BitString)38 BigDecimal (java.math.BigDecimal)35 RelBuilder (org.apache.calcite.tools.RelBuilder)34