Search in sources :

Example 16 with RexCall

use of org.apache.calcite.rex.RexCall in project calcite by apache.

the class LoptSemiJoinOptimizer method isSuitableFilter.

/**
 * Determines if a join filter can be used with a semijoin against a
 * specified fact table. A suitable filter is of the form "factable.col1 =
 * dimTable.col2".
 *
 * @param multiJoin join factors being optimized
 * @param joinFilter filter to be analyzed
 * @param factIdx index corresponding to the fact table
 *
 * @return index of corresponding dimension table if the filter is
 * appropriate; otherwise -1 is returned
 */
private int isSuitableFilter(LoptMultiJoin multiJoin, RexNode joinFilter, int factIdx) {
    // RexInputRefs
    switch(joinFilter.getKind()) {
        case EQUALS:
            break;
        default:
            return -1;
    }
    List<RexNode> operands = ((RexCall) joinFilter).getOperands();
    if (!(operands.get(0) instanceof RexInputRef) || !(operands.get(1) instanceof RexInputRef)) {
        return -1;
    }
    // filter is suitable if each side of the filter only contains a
    // single factor reference and one side references the fact table and
    // the other references the dimension table; since we know this is
    // a join filter and we've already verified that the operands are
    // RexInputRefs, verify that the factors belong to the fact and
    // dimension table
    ImmutableBitSet joinRefs = multiJoin.getFactorsRefByJoinFilter(joinFilter);
    assert joinRefs.cardinality() == 2;
    int factor1 = joinRefs.nextSetBit(0);
    int factor2 = joinRefs.nextSetBit(factor1 + 1);
    if (factor1 == factIdx) {
        return factor2;
    }
    if (factor2 == factIdx) {
        return factor1;
    }
    return -1;
}
Also used : RexCall(org.apache.calcite.rex.RexCall) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode)

Example 17 with RexCall

use of org.apache.calcite.rex.RexCall in project calcite by apache.

the class RelToSqlConverter method visit.

/**
 * @see #dispatch
 */
public Result visit(Match e) {
    final RelNode input = e.getInput();
    final Result x = visitChild(0, input);
    final Context context = matchRecognizeContext(x.qualifiedContext());
    SqlNode tableRef = x.asQueryOrValues();
    final List<SqlNode> partitionSqlList = new ArrayList<>();
    if (e.getPartitionKeys() != null) {
        for (RexNode rex : e.getPartitionKeys()) {
            SqlNode sqlNode = context.toSql(null, rex);
            partitionSqlList.add(sqlNode);
        }
    }
    final SqlNodeList partitionList = new SqlNodeList(partitionSqlList, POS);
    final List<SqlNode> orderBySqlList = new ArrayList<>();
    if (e.getOrderKeys() != null) {
        for (RelFieldCollation fc : e.getOrderKeys().getFieldCollations()) {
            if (fc.nullDirection != RelFieldCollation.NullDirection.UNSPECIFIED) {
                boolean first = fc.nullDirection == RelFieldCollation.NullDirection.FIRST;
                SqlNode nullDirectionNode = dialect.emulateNullDirection(context.field(fc.getFieldIndex()), first, fc.direction.isDescending());
                if (nullDirectionNode != null) {
                    orderBySqlList.add(nullDirectionNode);
                    fc = new RelFieldCollation(fc.getFieldIndex(), fc.getDirection(), RelFieldCollation.NullDirection.UNSPECIFIED);
                }
            }
            orderBySqlList.add(context.toSql(fc));
        }
    }
    final SqlNodeList orderByList = new SqlNodeList(orderBySqlList, SqlParserPos.ZERO);
    final SqlLiteral rowsPerMatch = e.isAllRows() ? SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS.symbol(POS) : SqlMatchRecognize.RowsPerMatchOption.ONE_ROW.symbol(POS);
    final SqlNode after;
    if (e.getAfter() instanceof RexLiteral) {
        SqlMatchRecognize.AfterOption value = (SqlMatchRecognize.AfterOption) ((RexLiteral) e.getAfter()).getValue2();
        after = SqlLiteral.createSymbol(value, POS);
    } else {
        RexCall call = (RexCall) e.getAfter();
        String operand = RexLiteral.stringValue(call.getOperands().get(0));
        after = call.getOperator().createCall(POS, new SqlIdentifier(operand, POS));
    }
    RexNode rexPattern = e.getPattern();
    final SqlNode pattern = context.toSql(null, rexPattern);
    final SqlLiteral strictStart = SqlLiteral.createBoolean(e.isStrictStart(), POS);
    final SqlLiteral strictEnd = SqlLiteral.createBoolean(e.isStrictEnd(), POS);
    RexLiteral rexInterval = (RexLiteral) e.getInterval();
    SqlIntervalLiteral interval = null;
    if (rexInterval != null) {
        interval = (SqlIntervalLiteral) context.toSql(null, rexInterval);
    }
    final SqlNodeList subsetList = new SqlNodeList(POS);
    for (Map.Entry<String, SortedSet<String>> entry : e.getSubsets().entrySet()) {
        SqlNode left = new SqlIdentifier(entry.getKey(), POS);
        List<SqlNode> rhl = Lists.newArrayList();
        for (String right : entry.getValue()) {
            rhl.add(new SqlIdentifier(right, POS));
        }
        subsetList.add(SqlStdOperatorTable.EQUALS.createCall(POS, left, new SqlNodeList(rhl, POS)));
    }
    final SqlNodeList measureList = new SqlNodeList(POS);
    for (Map.Entry<String, RexNode> entry : e.getMeasures().entrySet()) {
        final String alias = entry.getKey();
        final SqlNode sqlNode = context.toSql(null, entry.getValue());
        measureList.add(as(sqlNode, alias));
    }
    final SqlNodeList patternDefList = new SqlNodeList(POS);
    for (Map.Entry<String, RexNode> entry : e.getPatternDefinitions().entrySet()) {
        final String alias = entry.getKey();
        final SqlNode sqlNode = context.toSql(null, entry.getValue());
        patternDefList.add(as(sqlNode, alias));
    }
    final SqlNode matchRecognize = new SqlMatchRecognize(POS, tableRef, pattern, strictStart, strictEnd, patternDefList, measureList, after, subsetList, rowsPerMatch, partitionList, orderByList, interval);
    return result(matchRecognize, Expressions.list(Clause.FROM), e, null);
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) SqlIntervalLiteral(org.apache.calcite.sql.SqlIntervalLiteral) ArrayList(java.util.ArrayList) SqlMatchRecognize(org.apache.calcite.sql.SqlMatchRecognize) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SortedSet(java.util.SortedSet) RexCall(org.apache.calcite.rex.RexCall) RelNode(org.apache.calcite.rel.RelNode) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlLiteral(org.apache.calcite.sql.SqlLiteral) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode)

Example 18 with RexCall

use of org.apache.calcite.rex.RexCall in project calcite by apache.

the class SqlImplementor method convertConditionToSqlNode.

/**
 * Converts a {@link RexNode} condition into a {@link SqlNode}.
 *
 * @param node            Join condition
 * @param leftContext     Left context
 * @param rightContext    Right context
 * @param leftFieldCount  Number of fields on left result
 * @return SqlNode that represents the condition
 */
public static SqlNode convertConditionToSqlNode(RexNode node, Context leftContext, Context rightContext, int leftFieldCount) {
    if (node.isAlwaysTrue()) {
        return SqlLiteral.createBoolean(true, POS);
    }
    if (node.isAlwaysFalse()) {
        return SqlLiteral.createBoolean(false, POS);
    }
    if (!(node instanceof RexCall)) {
        throw new AssertionError(node);
    }
    final List<RexNode> operands;
    final SqlOperator op;
    final Context joinContext;
    switch(node.getKind()) {
        case AND:
        case OR:
            operands = ((RexCall) node).getOperands();
            op = ((RexCall) node).getOperator();
            SqlNode sqlCondition = null;
            for (RexNode operand : operands) {
                SqlNode x = convertConditionToSqlNode(operand, leftContext, rightContext, leftFieldCount);
                if (sqlCondition == null) {
                    sqlCondition = x;
                } else {
                    sqlCondition = op.createCall(POS, sqlCondition, x);
                }
            }
            return sqlCondition;
        case EQUALS:
        case IS_NOT_DISTINCT_FROM:
        case NOT_EQUALS:
        case GREATER_THAN:
        case GREATER_THAN_OR_EQUAL:
        case LESS_THAN:
        case LESS_THAN_OR_EQUAL:
            node = stripCastFromString(node);
            operands = ((RexCall) node).getOperands();
            op = ((RexCall) node).getOperator();
            if (operands.size() == 2 && operands.get(0) instanceof RexInputRef && operands.get(1) instanceof RexInputRef) {
                final RexInputRef op0 = (RexInputRef) operands.get(0);
                final RexInputRef op1 = (RexInputRef) operands.get(1);
                if (op0.getIndex() < leftFieldCount && op1.getIndex() >= leftFieldCount) {
                    // Arguments were of form 'op0 = op1'
                    return op.createCall(POS, leftContext.field(op0.getIndex()), rightContext.field(op1.getIndex() - leftFieldCount));
                }
                if (op1.getIndex() < leftFieldCount && op0.getIndex() >= leftFieldCount) {
                    // Arguments were of form 'op1 = op0'
                    return reverseOperatorDirection(op).createCall(POS, leftContext.field(op1.getIndex()), rightContext.field(op0.getIndex() - leftFieldCount));
                }
            }
            joinContext = leftContext.implementor().joinContext(leftContext, rightContext);
            return joinContext.toSql(null, node);
        case IS_NULL:
        case IS_NOT_NULL:
            operands = ((RexCall) node).getOperands();
            if (operands.size() == 1 && operands.get(0) instanceof RexInputRef) {
                op = ((RexCall) node).getOperator();
                final RexInputRef op0 = (RexInputRef) operands.get(0);
                if (op0.getIndex() < leftFieldCount) {
                    return op.createCall(POS, leftContext.field(op0.getIndex()));
                } else {
                    return op.createCall(POS, rightContext.field(op0.getIndex() - leftFieldCount));
                }
            }
            joinContext = leftContext.implementor().joinContext(leftContext, rightContext);
            return joinContext.toSql(null, node);
        default:
            throw new AssertionError(node);
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) SqlOperator(org.apache.calcite.sql.SqlOperator) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode) SqlNode(org.apache.calcite.sql.SqlNode)

Example 19 with RexCall

use of org.apache.calcite.rex.RexCall in project calcite by apache.

the class SqlImplementor method stripCastFromString.

/**
 * Removes cast from string.
 *
 * <p>For example, {@code x > CAST('2015-01-07' AS DATE)}
 * becomes {@code x > '2015-01-07'}.
 */
private static RexNode stripCastFromString(RexNode node) {
    switch(node.getKind()) {
        case EQUALS:
        case IS_NOT_DISTINCT_FROM:
        case NOT_EQUALS:
        case GREATER_THAN:
        case GREATER_THAN_OR_EQUAL:
        case LESS_THAN:
        case LESS_THAN_OR_EQUAL:
            final RexCall call = (RexCall) node;
            final RexNode o0 = call.operands.get(0);
            final RexNode o1 = call.operands.get(1);
            if (o0.getKind() == SqlKind.CAST && o1.getKind() != SqlKind.CAST) {
                final RexNode o0b = ((RexCall) o0).getOperands().get(0);
                switch(o0b.getType().getSqlTypeName()) {
                    case CHAR:
                    case VARCHAR:
                        return call.clone(call.getType(), ImmutableList.of(o0b, o1));
                }
            }
            if (o1.getKind() == SqlKind.CAST && o0.getKind() != SqlKind.CAST) {
                final RexNode o1b = ((RexCall) o1).getOperands().get(0);
                switch(o1b.getType().getSqlTypeName()) {
                    case CHAR:
                    case VARCHAR:
                        return call.clone(call.getType(), ImmutableList.of(o0, o1b));
                }
            }
    }
    return node;
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexNode(org.apache.calcite.rex.RexNode)

Example 20 with RexCall

use of org.apache.calcite.rex.RexCall in project calcite by apache.

the class RelMdUtil method getSelectivityValue.

/**
 * Returns the selectivity value stored in a call.
 *
 * @param artificialSelectivityFuncNode Call containing the selectivity value
 * @return selectivity value
 */
public static double getSelectivityValue(RexNode artificialSelectivityFuncNode) {
    assert artificialSelectivityFuncNode instanceof RexCall;
    RexCall call = (RexCall) artificialSelectivityFuncNode;
    assert call.getOperator() == ARTIFICIAL_SELECTIVITY_FUNC;
    RexNode operand = call.getOperands().get(0);
    return ((RexLiteral) operand).getValueAs(Double.class);
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexLiteral(org.apache.calcite.rex.RexLiteral) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RexCall (org.apache.calcite.rex.RexCall)213 RexNode (org.apache.calcite.rex.RexNode)172 RexInputRef (org.apache.calcite.rex.RexInputRef)61 ArrayList (java.util.ArrayList)59 RexLiteral (org.apache.calcite.rex.RexLiteral)44 Nullable (javax.annotation.Nullable)35 RelNode (org.apache.calcite.rel.RelNode)26 RelDataType (org.apache.calcite.rel.type.RelDataType)24 SqlOperator (org.apache.calcite.sql.SqlOperator)23 List (java.util.List)22 RexBuilder (org.apache.calcite.rex.RexBuilder)22 DruidExpression (org.apache.druid.sql.calcite.expression.DruidExpression)19 SqlKind (org.apache.calcite.sql.SqlKind)14 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)14 RelOptUtil (org.apache.calcite.plan.RelOptUtil)11 PostAggregator (org.apache.druid.query.aggregation.PostAggregator)11 RexCall (org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexCall)10 RexTableInputRef (org.apache.calcite.rex.RexTableInputRef)10 TimeUnitRange (org.apache.calcite.avatica.util.TimeUnitRange)9 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)9