Search in sources :

Example 1 with LogicalProject

use of org.apache.calcite.rel.logical.LogicalProject in project storm by apache.

the class TestRelNodeCompiler method testFilter.

@Test
public void testFilter() throws Exception {
    String sql = "SELECT ID + 1 FROM FOO WHERE ID > 3";
    TestCompilerUtils.CalciteState state = TestCompilerUtils.sqlOverDummyTable(sql);
    JavaTypeFactory typeFactory = new JavaTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
    LogicalProject project = (LogicalProject) state.tree();
    LogicalFilter filter = (LogicalFilter) project.getInput();
    try (StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw)) {
        RelNodeCompiler compiler = new RelNodeCompiler(pw, typeFactory);
        // standalone mode doesn't use inputstreams argument
        compiler.visitFilter(filter, Collections.EMPTY_LIST);
        pw.flush();
        Assert.assertThat(sw.toString(), containsString("> 3"));
    }
    try (StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw)) {
        RelNodeCompiler compiler = new RelNodeCompiler(pw, typeFactory);
        // standalone mode doesn't use inputstreams argument
        compiler.visitProject(project, Collections.EMPTY_LIST);
        pw.flush();
        Assert.assertThat(sw.toString(), containsString(" + 1"));
    }
}
Also used : StringWriter(java.io.StringWriter) JavaTypeFactoryImpl(org.apache.calcite.jdbc.JavaTypeFactoryImpl) LogicalFilter(org.apache.calcite.rel.logical.LogicalFilter) JavaTypeFactory(org.apache.calcite.adapter.java.JavaTypeFactory) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) PrintWriter(java.io.PrintWriter) Test(org.junit.Test)

Example 2 with LogicalProject

use of org.apache.calcite.rel.logical.LogicalProject in project calcite by apache.

the class SqlToRelConverter method convertMerge.

private RelNode convertMerge(SqlMerge call) {
    RelOptTable targetTable = getTargetTable(call);
    // convert update column list from SqlIdentifier to String
    final List<String> targetColumnNameList = new ArrayList<>();
    final RelDataType targetRowType = targetTable.getRowType();
    SqlUpdate updateCall = call.getUpdateCall();
    if (updateCall != null) {
        for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
            SqlIdentifier id = (SqlIdentifier) targetColumn;
            RelDataTypeField field = SqlValidatorUtil.getTargetField(targetRowType, typeFactory, id, catalogReader, targetTable);
            assert field != null : "column " + id.toString() + " not found";
            targetColumnNameList.add(field.getName());
        }
    }
    // replace the projection of the source select with a
    // projection that contains the following:
    // 1) the expressions corresponding to the new insert row (if there is
    // an insert)
    // 2) all columns from the target table (if there is an update)
    // 3) the set expressions in the update call (if there is an update)
    // first, convert the merge's source select to construct the columns
    // from the target table and the set expressions in the update call
    RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
    // then, convert the insert statement so we can get the insert
    // values expressions
    SqlInsert insertCall = call.getInsertCall();
    int nLevel1Exprs = 0;
    List<RexNode> level1InsertExprs = null;
    List<RexNode> level2InsertExprs = null;
    if (insertCall != null) {
        RelNode insertRel = convertInsert(insertCall);
        // if there are 2 level of projections in the insert source, combine
        // them into a single project; level1 refers to the topmost project;
        // the level1 projection contains references to the level2
        // expressions, except in the case where no target expression was
        // provided, in which case, the expression is the default value for
        // the column; or if the expressions directly map to the source
        // table
        level1InsertExprs = ((LogicalProject) insertRel.getInput(0)).getProjects();
        if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
            level2InsertExprs = ((LogicalProject) insertRel.getInput(0).getInput(0)).getProjects();
        }
        nLevel1Exprs = level1InsertExprs.size();
    }
    LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
    int nSourceFields = join.getLeft().getRowType().getFieldCount();
    final List<RexNode> projects = new ArrayList<>();
    for (int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
        if ((level2InsertExprs != null) && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
            int level2Idx = ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
            projects.add(level2InsertExprs.get(level2Idx));
        } else {
            projects.add(level1InsertExprs.get(level1Idx));
        }
    }
    if (updateCall != null) {
        final LogicalProject project = (LogicalProject) mergeSourceRel;
        projects.addAll(Util.skip(project.getProjects(), nSourceFields));
    }
    relBuilder.push(join).project(projects);
    return LogicalTableModify.create(targetTable, catalogReader, relBuilder.build(), LogicalTableModify.Operation.MERGE, targetColumnNameList, null, false);
}
Also used : ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlInsert(org.apache.calcite.sql.SqlInsert) SqlUpdate(org.apache.calcite.sql.SqlUpdate) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) LogicalJoin(org.apache.calcite.rel.logical.LogicalJoin) RexInputRef(org.apache.calcite.rex.RexInputRef) RelOptTable(org.apache.calcite.plan.RelOptTable) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with LogicalProject

use of org.apache.calcite.rel.logical.LogicalProject in project calcite by apache.

the class SqlToRelConverter method distinctify.

/**
 * Having translated 'SELECT ... FROM ... [GROUP BY ...] [HAVING ...]', adds
 * a relational expression to make the results unique.
 *
 * <p>If the SELECT clause contains duplicate expressions, adds
 * {@link org.apache.calcite.rel.logical.LogicalProject}s so that we are
 * grouping on the minimal set of keys. The performance gain isn't huge, but
 * it is difficult to detect these duplicate expressions later.
 *
 * @param bb               Blackboard
 * @param checkForDupExprs Check for duplicate expressions
 */
private void distinctify(Blackboard bb, boolean checkForDupExprs) {
    // Look for duplicate expressions in the project.
    // Say we have 'select x, y, x, z'.
    // Then dups will be {[2, 0]}
    // and oldToNew will be {[0, 0], [1, 1], [2, 0], [3, 2]}
    RelNode rel = bb.root;
    if (checkForDupExprs && (rel instanceof LogicalProject)) {
        LogicalProject project = (LogicalProject) rel;
        final List<RexNode> projectExprs = project.getProjects();
        final List<Integer> origins = new ArrayList<>();
        int dupCount = 0;
        for (int i = 0; i < projectExprs.size(); i++) {
            int x = findExpr(projectExprs.get(i), projectExprs, i);
            if (x >= 0) {
                origins.add(x);
                ++dupCount;
            } else {
                origins.add(i);
            }
        }
        if (dupCount == 0) {
            distinctify(bb, false);
            return;
        }
        final Map<Integer, Integer> squished = Maps.newHashMap();
        final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
        final List<Pair<RexNode, String>> newProjects = Lists.newArrayList();
        for (int i = 0; i < fields.size(); i++) {
            if (origins.get(i) == i) {
                squished.put(i, newProjects.size());
                newProjects.add(RexInputRef.of2(i, fields));
            }
        }
        rel = LogicalProject.create(rel, Pair.left(newProjects), Pair.right(newProjects));
        bb.root = rel;
        distinctify(bb, false);
        rel = bb.root;
        // Create the expressions to reverse the mapping.
        // Project($0, $1, $0, $2).
        final List<Pair<RexNode, String>> undoProjects = Lists.newArrayList();
        for (int i = 0; i < fields.size(); i++) {
            final int origin = origins.get(i);
            RelDataTypeField field = fields.get(i);
            undoProjects.add(Pair.of((RexNode) new RexInputRef(squished.get(origin), field.getType()), field.getName()));
        }
        rel = LogicalProject.create(rel, Pair.left(undoProjects), Pair.right(undoProjects));
        bb.setRoot(rel, false);
        return;
    }
    // Usual case: all of the expressions in the SELECT clause are
    // different.
    final ImmutableBitSet groupSet = ImmutableBitSet.range(rel.getRowType().getFieldCount());
    rel = createAggregate(bb, groupSet, ImmutableList.of(groupSet), ImmutableList.<AggregateCall>of());
    bb.setRoot(rel, false);
}
Also used : ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ArrayList(java.util.ArrayList) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexInputRef(org.apache.calcite.rex.RexInputRef) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair)

Example 4 with LogicalProject

use of org.apache.calcite.rel.logical.LogicalProject in project calcite by apache.

the class RelOptUtil method permute.

/**
 * Creates a relational expression which permutes the output fields of a
 * relational expression according to a permutation.
 *
 * <p>Optimizations:</p>
 *
 * <ul>
 * <li>If the relational expression is a
 * {@link org.apache.calcite.rel.logical.LogicalCalc} or
 * {@link org.apache.calcite.rel.logical.LogicalProject} that is already
 * acting as a permutation, combines the new permutation with the old;</li>
 *
 * <li>If the permutation is the identity, returns the original relational
 * expression.</li>
 * </ul>
 *
 * <p>If a permutation is combined with its inverse, these optimizations
 * would combine to remove them both.
 *
 * @param rel         Relational expression
 * @param permutation Permutation to apply to fields
 * @param fieldNames  Field names; if null, or if a particular entry is null,
 *                    the name of the permuted field is used
 * @return relational expression which permutes its input fields
 */
public static RelNode permute(RelNode rel, Permutation permutation, List<String> fieldNames) {
    if (permutation.isIdentity()) {
        return rel;
    }
    if (rel instanceof LogicalCalc) {
        LogicalCalc calc = (LogicalCalc) rel;
        Permutation permutation1 = calc.getProgram().getPermutation();
        if (permutation1 != null) {
            Permutation permutation2 = permutation.product(permutation1);
            return permute(rel, permutation2, null);
        }
    }
    if (rel instanceof LogicalProject) {
        Permutation permutation1 = ((LogicalProject) rel).getPermutation();
        if (permutation1 != null) {
            Permutation permutation2 = permutation.product(permutation1);
            return permute(rel, permutation2, null);
        }
    }
    final List<RelDataType> outputTypeList = new ArrayList<>();
    final List<String> outputNameList = new ArrayList<>();
    final List<RexNode> exprList = new ArrayList<>();
    final List<RexLocalRef> projectRefList = new ArrayList<>();
    final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
    final RelOptCluster cluster = rel.getCluster();
    for (int i = 0; i < permutation.getTargetCount(); i++) {
        int target = permutation.getTarget(i);
        final RelDataTypeField targetField = fields.get(target);
        outputTypeList.add(targetField.getType());
        outputNameList.add(((fieldNames == null) || (fieldNames.size() <= i) || (fieldNames.get(i) == null)) ? targetField.getName() : fieldNames.get(i));
        exprList.add(cluster.getRexBuilder().makeInputRef(fields.get(i).getType(), i));
        final int source = permutation.getSource(i);
        projectRefList.add(new RexLocalRef(source, fields.get(source).getType()));
    }
    final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
    final RexProgram program = new RexProgram(rel.getRowType(), exprList, projectRefList, null, typeFactory.createStructType(outputTypeList, outputNameList));
    return LogicalCalc.create(rel, program);
}
Also used : Permutation(org.apache.calcite.util.Permutation) RexProgram(org.apache.calcite.rex.RexProgram) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RexLocalRef(org.apache.calcite.rex.RexLocalRef) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) LogicalCalc(org.apache.calcite.rel.logical.LogicalCalc) RexNode(org.apache.calcite.rex.RexNode)

Example 5 with LogicalProject

use of org.apache.calcite.rel.logical.LogicalProject in project calcite by apache.

the class ProjectSetOpTransposeRule method onMatch.

// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
    LogicalProject origProj = call.rel(0);
    SetOp setOp = call.rel(1);
    // cannot push project past a distinct
    if (!setOp.all) {
        return;
    }
    // locate all fields referenced in the projection
    PushProjector pushProject = new PushProjector(origProj, null, setOp, preserveExprCondition, call.builder());
    pushProject.locateAllRefs();
    List<RelNode> newSetOpInputs = new ArrayList<>();
    int[] adjustments = pushProject.getAdjustments();
    // and it is the only operator this rule currently acts on
    for (RelNode input : setOp.getInputs()) {
        // be lazy:  produce two ProjectRels, and let another rule
        // merge them (could probably just clone origProj instead?)
        Project p = pushProject.createProjectRefsAndExprs(input, true, false);
        newSetOpInputs.add(pushProject.createNewProject(p, adjustments));
    }
    // create a new setop whose children are the ProjectRels created above
    SetOp newSetOp = setOp.copy(setOp.getTraitSet(), newSetOpInputs);
    call.transformTo(newSetOp);
}
Also used : Project(org.apache.calcite.rel.core.Project) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) SetOp(org.apache.calcite.rel.core.SetOp) RelNode(org.apache.calcite.rel.RelNode) ArrayList(java.util.ArrayList) LogicalProject(org.apache.calcite.rel.logical.LogicalProject)

Aggregations

LogicalProject (org.apache.calcite.rel.logical.LogicalProject)38 RexNode (org.apache.calcite.rex.RexNode)20 ArrayList (java.util.ArrayList)13 RelNode (org.apache.calcite.rel.RelNode)12 LogicalJoin (org.apache.calcite.rel.logical.LogicalJoin)11 LogicalFilter (org.apache.calcite.rel.logical.LogicalFilter)9 RelDataType (org.apache.calcite.rel.type.RelDataType)8 LogicalTableScan (org.apache.calcite.rel.logical.LogicalTableScan)6 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)6 RexBuilder (org.apache.calcite.rex.RexBuilder)6 Test (org.junit.Test)6 RexInputRef (org.apache.calcite.rex.RexInputRef)5 RelBuilder (org.apache.calcite.tools.RelBuilder)4 LogicalProject (org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.logical.LogicalProject)3 TableScan (org.apache.calcite.rel.core.TableScan)3 RexCall (org.apache.calcite.rex.RexCall)3 SqlOperator (org.apache.calcite.sql.SqlOperator)3 NlsString (org.apache.calcite.util.NlsString)3 ImmutableList (com.google.common.collect.ImmutableList)2 PrintWriter (java.io.PrintWriter)2