Search in sources :

Example 76 with RexCall

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexCall in project druid by druid-io.

the class FilterJoinExcludePushToChildRule method getConjunctions.

/**
 * Copied from {@link FilterJoinRule#getConjunctions}. Method is exactly the same as original.
 */
private List<RexNode> getConjunctions(Filter filter) {
    List<RexNode> conjunctions = RelOptUtil.conjunctions(filter.getCondition());
    RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
    for (int i = 0; i < conjunctions.size(); i++) {
        RexNode node = conjunctions.get(i);
        if (node instanceof RexCall) {
            conjunctions.set(i, RelOptUtil.collapseExpandedIsNotDistinctFromExpr((RexCall) node, rexBuilder));
        }
    }
    return conjunctions;
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 77 with RexCall

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexCall in project druid by druid-io.

the class DruidJoinRule method analyzeCondition.

/**
 * If this condition is an AND of some combination of (1) literals; (2) equality conditions of the form
 * {@code f(LeftRel) = RightColumn}, then return a {@link ConditionAnalysis}.
 */
private Optional<ConditionAnalysis> analyzeCondition(final RexNode condition, final RelDataType leftRowType, DruidRel<?> right) {
    final List<RexNode> subConditions = decomposeAnd(condition);
    final List<Pair<RexNode, RexInputRef>> equalitySubConditions = new ArrayList<>();
    final List<RexLiteral> literalSubConditions = new ArrayList<>();
    final int numLeftFields = leftRowType.getFieldCount();
    final Set<RexInputRef> rightColumns = new HashSet<>();
    for (RexNode subCondition : subConditions) {
        if (RexUtil.isLiteral(subCondition, true)) {
            if (subCondition.isA(SqlKind.CAST)) {
                // This is CAST(literal) which is always OK.
                // We know that this is CAST(literal) as it passed the check from RexUtil.isLiteral
                RexCall call = (RexCall) subCondition;
                // are different, then skipping the cast might change the meaning of the subcondition.
                if (call.getType().getSqlTypeName().equals(call.getOperands().get(0).getType().getSqlTypeName())) {
                    // If the types are the same, unwrap the cast and use the underlying literal.
                    literalSubConditions.add((RexLiteral) call.getOperands().get(0));
                } else {
                    // If the types are not the same, return Optional.empty() indicating the condition is not supported.
                    return Optional.empty();
                }
            } else {
                // Literals are always OK.
                literalSubConditions.add((RexLiteral) subCondition);
            }
            continue;
        }
        if (!subCondition.isA(SqlKind.EQUALS)) {
            // If it's not EQUALS, it's not supported.
            plannerContext.setPlanningError("SQL requires a join with '%s' condition that is not supported.", subCondition.getKind());
            return Optional.empty();
        }
        final List<RexNode> operands = ((RexCall) subCondition).getOperands();
        Preconditions.checkState(operands.size() == 2, "Expected 2 operands, got[%,d]", operands.size());
        if (isLeftExpression(operands.get(0), numLeftFields) && isRightInputRef(operands.get(1), numLeftFields)) {
            equalitySubConditions.add(Pair.of(operands.get(0), (RexInputRef) operands.get(1)));
            rightColumns.add((RexInputRef) operands.get(1));
        } else if (isRightInputRef(operands.get(0), numLeftFields) && isLeftExpression(operands.get(1), numLeftFields)) {
            equalitySubConditions.add(Pair.of(operands.get(1), (RexInputRef) operands.get(0)));
            rightColumns.add((RexInputRef) operands.get(0));
        } else {
            // Cannot handle this condition.
            plannerContext.setPlanningError("SQL is resulting in a join that has unsupported operand types.");
            return Optional.empty();
        }
    }
    // thereby allowing join conditions on both k and v columns of the lookup
    if (right != null && !DruidJoinQueryRel.computeRightRequiresSubquery(DruidJoinQueryRel.getSomeDruidChild(right)) && right instanceof DruidQueryRel) {
        DruidQueryRel druidQueryRel = (DruidQueryRel) right;
        if (druidQueryRel.getDruidTable().getDataSource() instanceof LookupDataSource) {
            long distinctRightColumns = rightColumns.stream().map(RexSlot::getIndex).distinct().count();
            if (distinctRightColumns > 1) {
                // it means that the join's right side is lookup and the join condition contains both key and value columns of lookup.
                // currently, the lookup datasource in the native engine doesn't support using value column in the join condition.
                plannerContext.setPlanningError("SQL is resulting in a join involving lookup where value column is used in the condition.");
                return Optional.empty();
            }
        }
    }
    return Optional.of(new ConditionAnalysis(numLeftFields, equalitySubConditions, literalSubConditions));
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) ArrayList(java.util.ArrayList) DruidQueryRel(org.apache.druid.sql.calcite.rel.DruidQueryRel) RexCall(org.apache.calcite.rex.RexCall) LookupDataSource(org.apache.druid.query.LookupDataSource) RexInputRef(org.apache.calcite.rex.RexInputRef) RexSlot(org.apache.calcite.rex.RexSlot) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.druid.java.util.common.Pair) HashSet(java.util.HashSet)

Example 78 with RexCall

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexCall in project druid by druid-io.

the class DruidJoinRule method decomposeAnd.

@VisibleForTesting
static List<RexNode> decomposeAnd(final RexNode condition) {
    final List<RexNode> retVal = new ArrayList<>();
    final Stack<RexNode> stack = new Stack<>();
    stack.push(condition);
    while (!stack.empty()) {
        final RexNode current = stack.pop();
        if (current.isA(SqlKind.AND)) {
            final List<RexNode> operands = ((RexCall) current).getOperands();
            // Add right-to-left, so when we unwind the stack, the operands are in the original order.
            for (int i = operands.size() - 1; i >= 0; i--) {
                stack.push(operands.get(i));
            }
        } else {
            retVal.add(current);
        }
    }
    return retVal;
}
Also used : RexCall(org.apache.calcite.rex.RexCall) ArrayList(java.util.ArrayList) RexNode(org.apache.calcite.rex.RexNode) Stack(java.util.Stack) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 79 with RexCall

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexCall in project druid by druid-io.

the class OperatorConversions method convertCall.

@Nullable
public static DruidExpression convertCall(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode, final DruidExpression.DruidExpressionBuilder expressionFunction) {
    final RexCall call = (RexCall) rexNode;
    final List<DruidExpression> druidExpressions = Expressions.toDruidExpressions(plannerContext, rowSignature, call.getOperands());
    if (druidExpressions == null) {
        return null;
    }
    return expressionFunction.buildExpression(druidExpressions);
}
Also used : RexCall(org.apache.calcite.rex.RexCall) Nullable(javax.annotation.Nullable)

Example 80 with RexCall

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexCall in project druid by druid-io.

the class OperatorConversions method convertCallWithPostAggOperands.

@Nullable
public static DruidExpression convertCallWithPostAggOperands(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode, final DruidExpression.DruidExpressionBuilder expressionFunction, final PostAggregatorVisitor postAggregatorVisitor) {
    final RexCall call = (RexCall) rexNode;
    final List<DruidExpression> druidExpressions = Expressions.toDruidExpressionsWithPostAggOperands(plannerContext, rowSignature, call.getOperands(), postAggregatorVisitor);
    if (druidExpressions == null) {
        return null;
    }
    return expressionFunction.buildExpression(druidExpressions);
}
Also used : RexCall(org.apache.calcite.rex.RexCall) Nullable(javax.annotation.Nullable)

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)60 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 RexNode (org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode)10 RexTableInputRef (org.apache.calcite.rex.RexTableInputRef)10 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)9