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);
}
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())));
}
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);
});
}
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());
}
}
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())));
}
Aggregations