Search in sources :

Example 11 with DruidExpression

use of org.apache.druid.sql.calcite.expression.DruidExpression in project druid by druid-io.

the class TimeFloorOperatorConversion method toDruidExpression.

@Override
@Nullable
public DruidExpression toDruidExpression(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode) {
    final RexCall call = (RexCall) rexNode;
    final List<DruidExpression> functionArgs = toTimestampFloorOrCeilArgs(plannerContext, rowSignature, call.getOperands());
    if (functionArgs == null) {
        return null;
    }
    return DruidExpression.ofFunctionCall(Calcites.getColumnTypeForRelDataType(rexNode.getType()), "timestamp_floor", functionArgs);
}
Also used : RexCall(org.apache.calcite.rex.RexCall) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) Nullable(javax.annotation.Nullable)

Example 12 with DruidExpression

use of org.apache.druid.sql.calcite.expression.DruidExpression in project druid by druid-io.

the class TimeParseOperatorConversion method toDruidExpression.

@Override
public DruidExpression toDruidExpression(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode) {
    final RexCall call = (RexCall) rexNode;
    final RexNode timeArg = call.getOperands().get(0);
    final DruidExpression timeExpression = Expressions.toDruidExpression(plannerContext, rowSignature, timeArg);
    if (timeExpression == null) {
        return null;
    }
    final String pattern = OperatorConversions.getOperandWithDefault(call.getOperands(), 1, RexLiteral::stringValue, null);
    final DateTimeZone timeZone = OperatorConversions.getOperandWithDefault(call.getOperands(), 2, operand -> DateTimes.inferTzFromString(RexLiteral.stringValue(operand)), plannerContext.getTimeZone());
    return DruidExpression.ofFunctionCall(Calcites.getColumnTypeForRelDataType(rexNode.getType()), "timestamp_parse", ImmutableList.of(timeExpression, DruidExpression.ofStringLiteral(pattern), DruidExpression.ofStringLiteral(timeZone.getID())));
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexLiteral(org.apache.calcite.rex.RexLiteral) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) DateTimeZone(org.joda.time.DateTimeZone) RexNode(org.apache.calcite.rex.RexNode)

Example 13 with DruidExpression

use of org.apache.druid.sql.calcite.expression.DruidExpression in project druid by druid-io.

the class TruncateOperatorConversion method toDruidExpression.

@Override
public DruidExpression toDruidExpression(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode) {
    return OperatorConversions.convertCallBuilder(plannerContext, rowSignature, rexNode, inputExpressions -> {
        final DruidExpression arg = inputExpressions.get(0);
        final Expr digitsExpr = inputExpressions.size() > 1 ? inputExpressions.get(1).parse(plannerContext.getExprMacroTable()) : null;
        final String factorString;
        if (digitsExpr == null) {
            factorString = "1";
        } else if (digitsExpr.isLiteral()) {
            final int digits = ((Number) digitsExpr.getLiteralValue()).intValue();
            final double factor = Math.pow(10, digits);
            factorString = DruidExpression.numberLiteral(factor);
        } else {
            factorString = StringUtils.format("pow(10,%s)", inputExpressions.get(1));
        }
        return StringUtils.format("(cast(cast(%s * %s,'long'),'double') / %s)", arg.getExpression(), factorString, factorString);
    });
}
Also used : DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) Expr(org.apache.druid.math.expr.Expr)

Example 14 with DruidExpression

use of org.apache.druid.sql.calcite.expression.DruidExpression in project druid by druid-io.

the class TimeArithmeticOperatorConversion method toDruidExpression.

@Override
public DruidExpression toDruidExpression(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode) {
    final RexCall call = (RexCall) rexNode;
    final List<RexNode> operands = call.getOperands();
    if (operands.size() != 2) {
        throw new IAE("Expected 2 args, got %s", operands.size());
    }
    final RexNode leftRexNode = operands.get(0);
    final RexNode rightRexNode = operands.get(1);
    final DruidExpression leftExpr = Expressions.toDruidExpression(plannerContext, rowSignature, leftRexNode);
    final DruidExpression rightExpr = Expressions.toDruidExpression(plannerContext, rowSignature, rightRexNode);
    if (leftExpr == null || rightExpr == null) {
        return null;
    }
    final ColumnType outputType = Calcites.getColumnTypeForRelDataType(rexNode.getType());
    if (rightRexNode.getType().getFamily() == SqlTypeFamily.INTERVAL_YEAR_MONTH) {
        // Period is a value in months.
        return DruidExpression.ofExpression(outputType, DruidExpression.functionCall("timestamp_shift"), ImmutableList.of(leftExpr, rightExpr.map(simpleExtraction -> null, expression -> rightRexNode.isA(SqlKind.LITERAL) ? StringUtils.format("'P%sM'", RexLiteral.value(rightRexNode)) : StringUtils.format("concat('P', %s, 'M')", expression)), DruidExpression.ofLiteral(ColumnType.LONG, DruidExpression.numberLiteral(direction > 0 ? 1 : -1)), DruidExpression.ofStringLiteral(plannerContext.getTimeZone().getID())));
    } else if (rightRexNode.getType().getFamily() == SqlTypeFamily.INTERVAL_DAY_TIME) {
        // Period is a value in milliseconds. Ignore time zone.
        return DruidExpression.ofExpression(outputType, (args) -> StringUtils.format("(%s %s %s)", args.get(0).getExpression(), direction > 0 ? "+" : "-", args.get(1).getExpression()), ImmutableList.of(leftExpr, rightExpr));
    } else if ((leftRexNode.getType().getFamily() == SqlTypeFamily.TIMESTAMP || leftRexNode.getType().getFamily() == SqlTypeFamily.DATE) && (rightRexNode.getType().getFamily() == SqlTypeFamily.TIMESTAMP || rightRexNode.getType().getFamily() == SqlTypeFamily.DATE)) {
        // Calcite represents both TIMESTAMP - INTERVAL and TIMESTAMPDIFF (TIMESTAMP - TIMESTAMP)
        // with a MINUS_DATE operator, so we must tell which case we're in by checking the type of
        // the second argument.
        Preconditions.checkState(direction < 0, "Time arithmetic require direction < 0");
        if (call.getType().getFamily() == SqlTypeFamily.INTERVAL_YEAR_MONTH) {
            return DruidExpression.ofExpression(outputType, DruidExpression.functionCall("subtract_months"), ImmutableList.of(leftExpr, rightExpr, DruidExpression.ofStringLiteral(plannerContext.getTimeZone().getID())));
        } else {
            return DruidExpression.ofExpression(outputType, (args) -> StringUtils.format("(%s %s %s)", args.get(0).getExpression(), "-", args.get(1).getExpression()), ImmutableList.of(leftExpr, rightExpr));
        }
    } else {
        // Shouldn't happen if subclasses are behaving.
        throw new ISE("Got unexpected type period type family[%s]", rightRexNode.getType().getFamily());
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) SqlKind(org.apache.calcite.sql.SqlKind) SqlTypeFamily(org.apache.calcite.sql.type.SqlTypeFamily) SqlOperatorConversion(org.apache.druid.sql.calcite.expression.SqlOperatorConversion) RexLiteral(org.apache.calcite.rex.RexLiteral) StringUtils(org.apache.druid.java.util.common.StringUtils) ISE(org.apache.druid.java.util.common.ISE) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) RexNode(org.apache.calcite.rex.RexNode) RowSignature(org.apache.druid.segment.column.RowSignature) PlannerContext(org.apache.druid.sql.calcite.planner.PlannerContext) ColumnType(org.apache.druid.segment.column.ColumnType) Preconditions(com.google.common.base.Preconditions) SqlOperator(org.apache.calcite.sql.SqlOperator) IAE(org.apache.druid.java.util.common.IAE) Calcites(org.apache.druid.sql.calcite.planner.Calcites) RexCall(org.apache.calcite.rex.RexCall) Expressions(org.apache.druid.sql.calcite.expression.Expressions) ColumnType(org.apache.druid.segment.column.ColumnType) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) ISE(org.apache.druid.java.util.common.ISE) IAE(org.apache.druid.java.util.common.IAE) RexNode(org.apache.calcite.rex.RexNode)

Example 15 with DruidExpression

use of org.apache.druid.sql.calcite.expression.DruidExpression in project druid by druid-io.

the class TimeFormatOperatorConversion method toDruidExpression.

@Override
public DruidExpression toDruidExpression(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode) {
    final RexCall call = (RexCall) rexNode;
    final RexNode timeArg = call.getOperands().get(0);
    final DruidExpression timeExpression = Expressions.toDruidExpression(plannerContext, rowSignature, timeArg);
    if (timeExpression == null) {
        return null;
    }
    final String pattern = OperatorConversions.getOperandWithDefault(call.getOperands(), 1, RexLiteral::stringValue, DEFAULT_PATTERN);
    final DateTimeZone timeZone = OperatorConversions.getOperandWithDefault(call.getOperands(), 2, operand -> {
        try {
            return DateTimes.inferTzFromString(RexLiteral.stringValue(operand), false);
        } catch (IllegalArgumentException e) {
            throw new IAE(e.getMessage());
        }
    }, plannerContext.getTimeZone());
    return DruidExpression.ofFunctionCall(Calcites.getColumnTypeForRelDataType(rexNode.getType()), "timestamp_format", ImmutableList.of(timeExpression, DruidExpression.ofStringLiteral(pattern), DruidExpression.ofStringLiteral(timeZone.getID())));
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexLiteral(org.apache.calcite.rex.RexLiteral) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) IAE(org.apache.druid.java.util.common.IAE) DateTimeZone(org.joda.time.DateTimeZone) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

DruidExpression (org.apache.druid.sql.calcite.expression.DruidExpression)53 RexNode (org.apache.calcite.rex.RexNode)34 Nullable (javax.annotation.Nullable)30 RexCall (org.apache.calcite.rex.RexCall)20 ColumnType (org.apache.druid.segment.column.ColumnType)15 AggregatorFactory (org.apache.druid.query.aggregation.AggregatorFactory)14 RexLiteral (org.apache.calcite.rex.RexLiteral)12 Aggregation (org.apache.druid.sql.calcite.aggregation.Aggregation)12 List (java.util.List)11 RowSignature (org.apache.druid.segment.column.RowSignature)11 RelDataType (org.apache.calcite.rel.type.RelDataType)10 Expressions (org.apache.druid.sql.calcite.expression.Expressions)10 SqlKind (org.apache.calcite.sql.SqlKind)9 PlannerContext (org.apache.druid.sql.calcite.planner.PlannerContext)9 RexBuilder (org.apache.calcite.rex.RexBuilder)8 SqlAggFunction (org.apache.calcite.sql.SqlAggFunction)8 SqlFunctionCategory (org.apache.calcite.sql.SqlFunctionCategory)8 ExprMacroTable (org.apache.druid.math.expr.ExprMacroTable)8 Collectors (java.util.stream.Collectors)7 AggregateCall (org.apache.calcite.rel.core.AggregateCall)7