Search in sources :

Example 1 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project drill by apache.

the class DrillOperatorTable method populateFromTypeInference.

private void populateFromTypeInference(SqlIdentifier opName, SqlFunctionCategory category, SqlSyntax syntax, List<SqlOperator> operatorList) {
    final List<SqlOperator> calciteOperatorList = Lists.newArrayList();
    inner.lookupOperatorOverloads(opName, category, syntax, calciteOperatorList);
    if (!calciteOperatorList.isEmpty()) {
        for (SqlOperator calciteOperator : calciteOperatorList) {
            if (calciteToWrapper.containsKey(calciteOperator)) {
                operatorList.add(calciteToWrapper.get(calciteOperator));
            } else {
                operatorList.add(calciteOperator);
            }
        }
    } else {
        // if no function is found, check in Drill UDFs
        if (operatorList.isEmpty() && (syntax == SqlSyntax.FUNCTION || syntax == SqlSyntax.FUNCTION_ID) && opName.isSimple()) {
            List<SqlOperator> drillOps = drillOperatorsWithInferenceMap.get(opName.getSimple().toLowerCase());
            if (drillOps != null && !drillOps.isEmpty()) {
                operatorList.addAll(drillOps);
            }
        }
    }
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator)

Example 2 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project drill by apache.

the class LocalFunctionRegistry method registerOperatorsWithoutInference.

private void registerOperatorsWithoutInference(DrillOperatorTable operatorTable, Map<String, Collection<DrillFuncHolder>> registeredFunctions) {
    SqlOperator op;
    for (Entry<String, Collection<DrillFuncHolder>> function : registeredFunctions.entrySet()) {
        Set<Integer> argCounts = Sets.newHashSet();
        String name = function.getKey().toUpperCase();
        for (DrillFuncHolder func : function.getValue()) {
            if (argCounts.add(func.getParamCount())) {
                if (func.isAggregating()) {
                    op = new DrillSqlAggOperatorWithoutInference(name, func.getParamCount());
                } else {
                    boolean isDeterministic;
                    // into literals
                    if (DrillConstExecutor.NON_REDUCIBLE_TYPES.contains(func.getReturnType().getMinorType())) {
                        isDeterministic = false;
                    } else {
                        isDeterministic = func.isDeterministic();
                    }
                    op = new DrillSqlOperatorWithoutInference(name, func.getParamCount(), func.getReturnType(), isDeterministic, func.isNiladic());
                }
                operatorTable.addOperatorWithoutInference(function.getKey(), op);
            }
        }
    }
}
Also used : DrillFuncHolder(org.apache.drill.exec.expr.fn.DrillFuncHolder) DrillSqlAggOperatorWithoutInference(org.apache.drill.exec.planner.sql.DrillSqlAggOperatorWithoutInference) DrillSqlOperator(org.apache.drill.exec.planner.sql.DrillSqlOperator) SqlOperator(org.apache.calcite.sql.SqlOperator) DrillSqlOperatorWithoutInference(org.apache.drill.exec.planner.sql.DrillSqlOperatorWithoutInference) Collection(java.util.Collection)

Example 3 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project drill by apache.

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);
    final RelDataType sumType = typeFactory.createTypeWithNullability(argType, true);
    final AggregateCall sumArgSquaredAggCall = AggregateCall.create(new SqlSumAggFunction(sumType), oldCall.isDistinct(), 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 SqlSumAggFunction(sumType), oldCall.isDistinct(), 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.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().getSqlTypeName());
        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) 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) 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 4 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project drill by apache.

the class RewriteAsBinaryOperators method visitCall.

@Override
public RexNode visitCall(RexCall call) {
    SqlOperator op = call.getOperator();
    SqlKind kind = op.getKind();
    RelDataType type = call.getType();
    if (kind == SqlKind.OR || kind == SqlKind.AND) {
        if (call.getOperands().size() > 2) {
            List<RexNode> children = new ArrayList<>(call.getOperands());
            RexNode left = children.remove(0).accept(this);
            RexNode right = builder.makeCall(type, op, children).accept(this);
            return builder.makeCall(type, op, ImmutableList.of(left, right));
        }
    }
    return builder.makeCall(type, op, visitChildren(call));
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlKind(org.apache.calcite.sql.SqlKind) RexNode(org.apache.calcite.rex.RexNode)

Example 5 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project drill by apache.

the class PreProcessLogicalRel method getConvertFunctionException.

private UserException getConvertFunctionException(final String functionName, final String typeName) {
    final String newFunctionName = functionName + typeName;
    final String typeNameToPrint = typeName.length() == 0 ? "<empty_string>" : typeName;
    final UserException.Builder exceptionBuilder = UserException.unsupportedError().message("%s does not support conversion %s type '%s'.", functionName, functionName.substring(8).toLowerCase(), typeNameToPrint);
    // Build a nice error message
    if (typeName.length() > 0) {
        List<String> ops = new ArrayList<>();
        for (SqlOperator op : table.getOperatorList()) {
            ops.add(op.getName());
        }
        final String bestMatch = ApproximateStringMatcher.getBestMatch(ops, newFunctionName);
        if (bestMatch != null && bestMatch.length() > 0 && bestMatch.toLowerCase().startsWith("convert")) {
            final StringBuilder s = new StringBuilder("Did you mean ").append(bestMatch.substring(functionName.length())).append("?");
            exceptionBuilder.addContext(s.toString());
        }
    }
    return exceptionBuilder.build(logger);
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) ArrayList(java.util.ArrayList) NlsString(org.apache.calcite.util.NlsString) UserException(org.apache.drill.common.exceptions.UserException)

Aggregations

SqlOperator (org.apache.calcite.sql.SqlOperator)14 ArrayList (java.util.ArrayList)6 RexNode (org.apache.calcite.rex.RexNode)6 RelDataType (org.apache.calcite.rel.type.RelDataType)5 SqlKind (org.apache.calcite.sql.SqlKind)3 RexBuilder (org.apache.calcite.rex.RexBuilder)2 RexCall (org.apache.calcite.rex.RexCall)2 RexLiteral (org.apache.calcite.rex.RexLiteral)2 SqlFunction (org.apache.calcite.sql.SqlFunction)2 NlsString (org.apache.calcite.util.NlsString)2 DrillSqlOperator (org.apache.drill.exec.planner.sql.DrillSqlOperator)2 CalciteSemanticException (org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSemanticException)2 ImmutableList (com.google.common.collect.ImmutableList)1 SqlAggregator (io.druid.sql.calcite.aggregation.SqlAggregator)1 SqlExtractionOperator (io.druid.sql.calcite.expression.SqlExtractionOperator)1 BigDecimal (java.math.BigDecimal)1 Collection (java.util.Collection)1 List (java.util.List)1 RelTraitSet (org.apache.calcite.plan.RelTraitSet)1 RelNode (org.apache.calcite.rel.RelNode)1