Search in sources :

Example 41 with RexLiteral

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

the class ValuesReduceRule method apply.

// ~ Methods ----------------------------------------------------------------
/**
 * Does the work.
 *
 * @param call    Rule call
 * @param project Project, may be null
 * @param filter  Filter, may be null
 * @param values  Values rel to be reduced
 */
protected void apply(RelOptRuleCall call, LogicalProject project, LogicalFilter filter, LogicalValues values) {
    assert values != null;
    assert filter != null || project != null;
    final RexNode conditionExpr = (filter == null) ? null : filter.getCondition();
    final List<RexNode> projectExprs = (project == null) ? null : project.getProjects();
    RexBuilder rexBuilder = values.getCluster().getRexBuilder();
    // Find reducible expressions.
    final List<RexNode> reducibleExps = new ArrayList<>();
    final MyRexShuttle shuttle = new MyRexShuttle();
    for (final List<RexLiteral> literalList : values.getTuples()) {
        shuttle.literalList = literalList;
        if (conditionExpr != null) {
            RexNode c = conditionExpr.accept(shuttle);
            reducibleExps.add(c);
        }
        if (projectExprs != null) {
            int k = -1;
            for (RexNode projectExpr : projectExprs) {
                ++k;
                RexNode e = projectExpr.accept(shuttle);
                if (RexLiteral.isNullLiteral(e)) {
                    e = rexBuilder.makeAbstractCast(project.getRowType().getFieldList().get(k).getType(), e);
                }
                reducibleExps.add(e);
            }
        }
    }
    int fieldsPerRow = ((conditionExpr == null) ? 0 : 1) + ((projectExprs == null) ? 0 : projectExprs.size());
    assert fieldsPerRow > 0;
    assert reducibleExps.size() == (values.getTuples().size() * fieldsPerRow);
    // Compute the values they reduce to.
    final RelOptPredicateList predicates = RelOptPredicateList.EMPTY;
    ReduceExpressionsRule.reduceExpressions(values, reducibleExps, predicates, false, true);
    int changeCount = 0;
    final ImmutableList.Builder<ImmutableList<RexLiteral>> tuplesBuilder = ImmutableList.builder();
    for (int row = 0; row < values.getTuples().size(); ++row) {
        int i = 0;
        RexNode reducedValue;
        if (conditionExpr != null) {
            reducedValue = reducibleExps.get((row * fieldsPerRow) + i);
            ++i;
            if (!reducedValue.isAlwaysTrue()) {
                ++changeCount;
                continue;
            }
        }
        ImmutableList<RexLiteral> valuesList;
        if (projectExprs != null) {
            ++changeCount;
            final ImmutableList.Builder<RexLiteral> tupleBuilder = ImmutableList.builder();
            for (; i < fieldsPerRow; ++i) {
                reducedValue = reducibleExps.get((row * fieldsPerRow) + i);
                if (reducedValue instanceof RexLiteral) {
                    tupleBuilder.add((RexLiteral) reducedValue);
                } else if (RexUtil.isNullLiteral(reducedValue, true)) {
                    tupleBuilder.add(rexBuilder.constantNull());
                } else {
                    return;
                }
            }
            valuesList = tupleBuilder.build();
        } else {
            valuesList = values.getTuples().get(row);
        }
        tuplesBuilder.add(valuesList);
    }
    if (changeCount > 0) {
        final RelDataType rowType;
        if (projectExprs != null) {
            rowType = project.getRowType();
        } else {
            rowType = values.getRowType();
        }
        final RelNode newRel = LogicalValues.create(values.getCluster(), rowType, tuplesBuilder.build());
        call.transformTo(newRel);
    } else {
        // Filter had no effect, so we can say that Filter(Values) ==
        // Values.
        call.transformTo(values);
    }
    // can send the volcano planner into a loop; see dtbug 2070.)
    if (filter != null) {
        call.getPlanner().setImportance(filter, 0.0);
    }
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) ImmutableList(com.google.common.collect.ImmutableList) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) RelNode(org.apache.calcite.rel.RelNode) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 42 with RexLiteral

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

the class ExtractOperatorConversion method toDruidExpression.

@Override
public String toDruidExpression(RexNode rexNode, RelDataType rowType, DruidQuery query) {
    final RexCall call = (RexCall) rexNode;
    final RexLiteral flag = (RexLiteral) call.getOperands().get(0);
    final TimeUnitRange calciteUnit = (TimeUnitRange) flag.getValue();
    final RexNode arg = call.getOperands().get(1);
    final String input = DruidExpressions.toDruidExpression(arg, rowType, query);
    if (input == null) {
        return null;
    }
    final String druidUnit = EXTRACT_UNIT_MAP.get(calciteUnit);
    if (druidUnit == null) {
        return null;
    }
    return DruidExpressions.applyTimeExtract(input, druidUnit, TimeZone.getTimeZone(query.getConnectionConfig().timeZone()));
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexLiteral(org.apache.calcite.rex.RexLiteral) TimeUnitRange(org.apache.calcite.avatica.util.TimeUnitRange) RexNode(org.apache.calcite.rex.RexNode)

Example 43 with RexLiteral

use of org.apache.calcite.rex.RexLiteral in project drill by axbaretto.

the class DrillReduceAggregatesRule method reduceStddev.

private RexNode reduceStddev(Aggregate oldAggRel, AggregateCall oldCall, boolean biased, boolean sqrt, List<AggregateCall> newCalls, Map<AggregateCall, RexNode> aggCallMapping, List<RexNode> inputExprs) {
    // stddev_pop(x) ==>
    // power(
    // (sum(x * x) - sum(x) * sum(x) / count(x))
    // / count(x),
    // .5)
    // 
    // stddev_samp(x) ==>
    // power(
    // (sum(x * x) - sum(x) * sum(x) / count(x))
    // / nullif(count(x) - 1, 0),
    // .5)
    final PlannerSettings plannerSettings = (PlannerSettings) oldAggRel.getCluster().getPlanner().getContext();
    final boolean isInferenceEnabled = plannerSettings.isTypeInferenceEnabled();
    final int nGroups = oldAggRel.getGroupCount();
    RelDataTypeFactory typeFactory = oldAggRel.getCluster().getTypeFactory();
    final RexBuilder rexBuilder = oldAggRel.getCluster().getRexBuilder();
    assert oldCall.getArgList().size() == 1 : oldCall.getArgList();
    final int argOrdinal = oldCall.getArgList().get(0);
    final RelDataType argType = getFieldType(oldAggRel.getInput(), argOrdinal);
    // final RexNode argRef = inputExprs.get(argOrdinal);
    RexNode argRef = rexBuilder.makeCall(CastHighOp, inputExprs.get(argOrdinal));
    inputExprs.set(argOrdinal, argRef);
    final RexNode argSquared = rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, argRef, argRef);
    final int argSquaredOrdinal = lookupOrAdd(inputExprs, argSquared);
    RelDataType sumType = TypeInferenceUtils.getDrillSqlReturnTypeInference(SqlKind.SUM.name(), ImmutableList.<DrillFuncHolder>of()).inferReturnType(oldCall.createBinding(oldAggRel));
    sumType = typeFactory.createTypeWithNullability(sumType, true);
    final AggregateCall sumArgSquaredAggCall = AggregateCall.create(new DrillCalciteSqlAggFunctionWrapper(new SqlSumAggFunction(sumType), sumType), oldCall.isDistinct(), oldCall.isApproximate(), ImmutableIntList.of(argSquaredOrdinal), -1, sumType, null);
    final RexNode sumArgSquared = rexBuilder.addAggCall(sumArgSquaredAggCall, nGroups, oldAggRel.indicator, newCalls, aggCallMapping, ImmutableList.of(argType));
    final AggregateCall sumArgAggCall = AggregateCall.create(new DrillCalciteSqlAggFunctionWrapper(new SqlSumAggFunction(sumType), sumType), oldCall.isDistinct(), oldCall.isApproximate(), ImmutableIntList.of(argOrdinal), -1, sumType, null);
    final RexNode sumArg = rexBuilder.addAggCall(sumArgAggCall, nGroups, oldAggRel.indicator, newCalls, aggCallMapping, ImmutableList.of(argType));
    final RexNode sumSquaredArg = rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, sumArg, sumArg);
    final SqlCountAggFunction countAgg = (SqlCountAggFunction) SqlStdOperatorTable.COUNT;
    final RelDataType countType = countAgg.getReturnType(typeFactory);
    final AggregateCall countArgAggCall = AggregateCall.create(countAgg, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.getArgList(), -1, countType, null);
    final RexNode countArg = rexBuilder.addAggCall(countArgAggCall, nGroups, oldAggRel.indicator, newCalls, aggCallMapping, ImmutableList.of(argType));
    final RexNode avgSumSquaredArg = rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, sumSquaredArg, countArg);
    final RexNode diff = rexBuilder.makeCall(SqlStdOperatorTable.MINUS, sumArgSquared, avgSumSquaredArg);
    final RexNode denominator;
    if (biased) {
        denominator = countArg;
    } else {
        final RexLiteral one = rexBuilder.makeExactLiteral(BigDecimal.ONE);
        final RexNode nul = rexBuilder.makeNullLiteral(countArg.getType());
        final RexNode countMinusOne = rexBuilder.makeCall(SqlStdOperatorTable.MINUS, countArg, one);
        final RexNode countEqOne = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, countArg, one);
        denominator = rexBuilder.makeCall(SqlStdOperatorTable.CASE, countEqOne, nul, countMinusOne);
    }
    final SqlOperator divide;
    if (isInferenceEnabled) {
        divide = new DrillSqlOperator("divide", 2, true, oldCall.getType(), false);
    } else {
        divide = SqlStdOperatorTable.DIVIDE;
    }
    final RexNode div = rexBuilder.makeCall(divide, diff, denominator);
    RexNode result = div;
    if (sqrt) {
        final RexNode half = rexBuilder.makeExactLiteral(new BigDecimal("0.5"));
        result = rexBuilder.makeCall(SqlStdOperatorTable.POWER, div, half);
    }
    if (isInferenceEnabled) {
        return result;
    } else {
        /*
      * Currently calcite's strategy to infer the return type of aggregate functions
      * is wrong because it uses the first known argument to determine output type. For
      * instance if we are performing stddev on an integer column then it interprets the
      * output type to be integer which is incorrect as it should be double. So based on
      * this if we add cast after rewriting the aggregate we add an additional cast which
      * would cause wrong results. So we simply add a cast to ANY.
      */
        return rexBuilder.makeCast(typeFactory.createSqlType(SqlTypeName.ANY), result);
    }
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) DrillFuncHolder(org.apache.drill.exec.expr.fn.DrillFuncHolder) PlannerSettings(org.apache.drill.exec.planner.physical.PlannerSettings) DrillSqlOperator(org.apache.drill.exec.planner.sql.DrillSqlOperator) SqlOperator(org.apache.calcite.sql.SqlOperator) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlCountAggFunction(org.apache.calcite.sql.fun.SqlCountAggFunction) BigDecimal(java.math.BigDecimal) DrillCalciteSqlAggFunctionWrapper(org.apache.drill.exec.planner.sql.DrillCalciteSqlAggFunctionWrapper) DrillSqlOperator(org.apache.drill.exec.planner.sql.DrillSqlOperator) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) SqlSumAggFunction(org.apache.calcite.sql.fun.SqlSumAggFunction) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 44 with RexLiteral

use of org.apache.calcite.rex.RexLiteral in project drill by apache.

the class DrillRexBuilder method makeCast.

/**
 * Creates a call to the CAST operator, expanding if possible, and optionally
 * also preserving nullability.
 *
 * <p>Tries to expand the cast, and therefore the result may be something
 * other than a {@link org.apache.calcite.rex.RexCall} to the CAST operator, such as a
 * {@link RexLiteral} if {@code matchNullability} is false.
 *
 * @param type             Type to cast to
 * @param exp              Expression being cast
 * @param matchNullability Whether to ensure the result has the same
 *                         nullability as {@code type}
 * @return Call to CAST operator
 */
@Override
public RexNode makeCast(RelDataType type, RexNode exp, boolean matchNullability) {
    if (matchNullability) {
        return makeAbstractCast(type, exp);
    }
    // TODO: remove this code when CALCITE-1468 is fixed
    if (type.getSqlTypeName() == SqlTypeName.DECIMAL && exp instanceof RexLiteral) {
        int precision = type.getPrecision();
        int scale = type.getScale();
        validatePrecisionAndScale(precision, scale);
        Comparable<?> value = ((RexLiteral) exp).getValueAs(Comparable.class);
        if (value instanceof BigDecimal) {
            BigDecimal bigDecimal = (BigDecimal) value;
            DecimalUtility.checkValueOverflow(bigDecimal, precision, scale);
            if (bigDecimal.precision() != precision || bigDecimal.scale() != scale) {
                return makeAbstractCast(type, exp);
            }
        }
    }
    return super.makeCast(type, exp, false);
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) BigDecimal(java.math.BigDecimal)

Example 45 with RexLiteral

use of org.apache.calcite.rex.RexLiteral in project drill by apache.

the class JoinUtils method isScalarSubquery.

/**
 * Utility method to check if a subquery (represented by its root RelNode) is provably scalar. Currently
 * only aggregates with no group-by are considered scalar. In the future, this method should be generalized
 * to include more cases and reconciled with Calcite's notion of scalar.
 * @param root The root RelNode to be examined
 * @return True if the root rel or its descendant is scalar, False otherwise
 */
public static boolean isScalarSubquery(RelNode root) {
    DrillAggregateRel agg = null;
    RelNode currentrel = root;
    while (agg == null && currentrel != null) {
        if (currentrel instanceof DrillAggregateRel) {
            agg = (DrillAggregateRel) currentrel;
        } else if (currentrel instanceof RelSubset) {
            currentrel = ((RelSubset) currentrel).getBest();
        } else if (currentrel instanceof DrillLimitRel) {
            // TODO: Improve this check when DRILL-5691 is fixed.
            // The problem is that RelMdMaxRowCount currently cannot be used
            // due to CALCITE-1048.
            Integer fetchValue = ((RexLiteral) ((DrillLimitRel) currentrel).getFetch()).getValueAs(Integer.class);
            return fetchValue != null && fetchValue <= 1;
        } else if (currentrel.getInputs().size() == 1) {
            // If the rel is not an aggregate or RelSubset, but is a single-input rel (could be Project,
            // Filter, Sort etc.), check its input
            currentrel = currentrel.getInput(0);
        } else {
            break;
        }
    }
    if (agg != null) {
        if (agg.getGroupSet().isEmpty()) {
            return true;
        }
        // with empty call list and literal from project expression in group set.
        if (agg.getAggCallList().isEmpty() && agg.getGroupSet().cardinality() == 1) {
            ProjectExpressionsCollector expressionsCollector = new ProjectExpressionsCollector();
            agg.accept(expressionsCollector);
            List<RexNode> projectedExpressions = expressionsCollector.getProjectedExpressions();
            return projectedExpressions.size() == 1 && RexUtil.isLiteral(projectedExpressions.get(agg.getGroupSet().nth(0)), true);
        }
    }
    return false;
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) RelNode(org.apache.calcite.rel.RelNode) DrillAggregateRel(org.apache.drill.exec.planner.logical.DrillAggregateRel) RelSubset(org.apache.calcite.plan.volcano.RelSubset) DrillLimitRel(org.apache.drill.exec.planner.logical.DrillLimitRel) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RexLiteral (org.apache.calcite.rex.RexLiteral)150 RexNode (org.apache.calcite.rex.RexNode)92 ArrayList (java.util.ArrayList)51 RelDataType (org.apache.calcite.rel.type.RelDataType)45 RexCall (org.apache.calcite.rex.RexCall)45 Test (org.junit.Test)32 BigDecimal (java.math.BigDecimal)28 RexInputRef (org.apache.calcite.rex.RexInputRef)26 RelNode (org.apache.calcite.rel.RelNode)22 ImmutableList (com.google.common.collect.ImmutableList)18 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)17 List (java.util.List)16 Map (java.util.Map)16 RexBuilder (org.apache.calcite.rex.RexBuilder)16 AggregateCall (org.apache.calcite.rel.core.AggregateCall)15 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)12 RexLiteral (org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexLiteral)11 NlsString (org.apache.calcite.util.NlsString)11 HashMap (java.util.HashMap)10 RexNode (org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode)10