use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class RexImpTable method implementCall.
private static Expression implementCall(final RexToLixTranslator translator, RexCall call, NotNullImplementor implementor, final NullAs nullAs) {
List<Expression> translatedOperands = translator.translateList(call.getOperands());
// handled for nulls before being passed to the NotNullImplementor.
if (nullAs == NullAs.NOT_POSSIBLE) {
List<Expression> nullHandled = translatedOperands;
for (int i = 0; i < translatedOperands.size(); i++) {
RexNode arg = call.getOperands().get(i);
Expression e = translatedOperands.get(i);
if (!translator.isNullable(arg)) {
if (nullHandled == translatedOperands) {
nullHandled = new ArrayList<>(translatedOperands.subList(0, i));
}
nullHandled.add(translator.handleNull(e, nullAs));
} else if (nullHandled != translatedOperands) {
nullHandled.add(e);
}
}
translatedOperands = nullHandled;
}
Expression result = implementor.implement(translator, call, translatedOperands);
return translator.handleNull(result, nullAs);
}
use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class RexToLixTranslator method translate0.
/**
* Translates an expression that is not in the cache.
*
* @param expr Expression
* @param nullAs If false, if expression is definitely not null at
* runtime. Therefore we can optimize. For example, we can cast to int
* using x.intValue().
* @return Translated expression
*/
private Expression translate0(RexNode expr, RexImpTable.NullAs nullAs, Type storageType) {
if (nullAs == RexImpTable.NullAs.NULL && !expr.getType().isNullable()) {
nullAs = RexImpTable.NullAs.NOT_POSSIBLE;
}
switch(expr.getKind()) {
case INPUT_REF:
final int index = ((RexInputRef) expr).getIndex();
Expression x = inputGetter.field(list, index, storageType);
// safe to share
Expression input = list.append("inp" + index + "_", x);
if (nullAs == RexImpTable.NullAs.NOT_POSSIBLE && input.type.equals(storageType)) {
// unboxing via nullAs.handle below.
return input;
}
return handleNull(input, nullAs);
case LOCAL_REF:
return translate(deref(expr), nullAs, storageType);
case LITERAL:
return translateLiteral((RexLiteral) expr, nullifyType(expr.getType(), isNullable(expr) && nullAs != RexImpTable.NullAs.NOT_POSSIBLE), typeFactory, nullAs);
case DYNAMIC_PARAM:
return translateParameter((RexDynamicParam) expr, nullAs, storageType);
case CORREL_VARIABLE:
throw new RuntimeException("Cannot translate " + expr + ". Correlated" + " variables should always be referenced by field access");
case FIELD_ACCESS:
RexFieldAccess fieldAccess = (RexFieldAccess) expr;
RexNode target = deref(fieldAccess.getReferenceExpr());
// only $cor.field access is supported
if (!(target instanceof RexCorrelVariable)) {
throw new RuntimeException("cannot translate expression " + expr);
}
if (correlates == null) {
throw new RuntimeException("Cannot translate " + expr + " since " + "correlate variables resolver is not defined");
}
InputGetter getter = correlates.apply(((RexCorrelVariable) target).getName());
return getter.field(list, fieldAccess.getField().getIndex(), storageType);
default:
if (expr instanceof RexCall) {
return translateCall((RexCall) expr, nullAs);
}
throw new RuntimeException("cannot translate expression " + expr);
}
}
use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class RexToLixTranslator method translateConstructor.
public Expression translateConstructor(List<RexNode> operandList, SqlKind kind) {
switch(kind) {
case MAP_VALUE_CONSTRUCTOR:
Expression map = list.append("map", Expressions.new_(LinkedHashMap.class), false);
for (int i = 0; i < operandList.size(); i++) {
RexNode key = operandList.get(i++);
RexNode value = operandList.get(i);
list.add(Expressions.statement(Expressions.call(map, BuiltInMethod.MAP_PUT.method, Expressions.box(translate(key)), Expressions.box(translate(value)))));
}
return map;
case ARRAY_VALUE_CONSTRUCTOR:
Expression lyst = list.append("list", Expressions.new_(ArrayList.class), false);
for (RexNode value : operandList) {
list.add(Expressions.statement(Expressions.call(lyst, BuiltInMethod.COLLECTION_ADD.method, Expressions.box(translate(value)))));
}
return lyst;
default:
throw new AssertionError("unexpected: " + kind);
}
}
use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class RexToLixTranslator method translateCast.
Expression translateCast(RelDataType sourceType, RelDataType targetType, Expression operand) {
Expression convert = null;
switch(targetType.getSqlTypeName()) {
case ANY:
convert = operand;
break;
case DATE:
switch(sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
convert = Expressions.call(BuiltInMethod.STRING_TO_DATE.method, operand);
break;
case TIMESTAMP:
convert = Expressions.convert_(Expressions.call(BuiltInMethod.FLOOR_DIV.method, operand, Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)), int.class);
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_DATE.method, operand, Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
}
break;
case TIME:
switch(sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
convert = Expressions.call(BuiltInMethod.STRING_TO_TIME.method, operand);
break;
case TIME_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIME_WITH_LOCAL_TIME_ZONE_TO_TIME.method, operand, Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
case TIMESTAMP:
convert = Expressions.convert_(Expressions.call(BuiltInMethod.FLOOR_MOD.method, operand, Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)), int.class);
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_TIME.method, operand, Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
}
break;
case TIME_WITH_LOCAL_TIME_ZONE:
switch(sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
convert = Expressions.call(BuiltInMethod.STRING_TO_TIME_WITH_LOCAL_TIME_ZONE.method, operand);
break;
case TIME:
convert = Expressions.call(BuiltInMethod.TIME_STRING_TO_TIME_WITH_LOCAL_TIME_ZONE.method, RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.UNIX_TIME_TO_STRING.method, operand)), Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
break;
case TIMESTAMP:
convert = Expressions.call(BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method, RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method, operand)), Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_TIME_WITH_LOCAL_TIME_ZONE.method, operand));
}
break;
case TIMESTAMP:
switch(sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
convert = Expressions.call(BuiltInMethod.STRING_TO_TIMESTAMP.method, operand);
break;
case DATE:
convert = Expressions.multiply(Expressions.convert_(operand, long.class), Expressions.constant(DateTimeUtils.MILLIS_PER_DAY));
break;
case TIME:
convert = Expressions.add(Expressions.multiply(Expressions.convert_(Expressions.call(BuiltInMethod.CURRENT_DATE.method, root), long.class), Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)), Expressions.convert_(operand, long.class));
break;
case TIME_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIME_WITH_LOCAL_TIME_ZONE_TO_TIMESTAMP.method, Expressions.call(BuiltInMethod.UNIX_DATE_TO_STRING.method, Expressions.call(BuiltInMethod.CURRENT_DATE.method, root)), operand, Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_TIMESTAMP.method, operand, Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
}
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
switch(sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
convert = Expressions.call(BuiltInMethod.STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method, operand);
break;
case DATE:
convert = Expressions.call(BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method, RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method, Expressions.multiply(Expressions.convert_(operand, long.class), Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)))), Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
break;
case TIME:
convert = Expressions.call(BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method, RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method, Expressions.add(Expressions.multiply(Expressions.convert_(Expressions.call(BuiltInMethod.CURRENT_DATE.method, root), long.class), Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)), Expressions.convert_(operand, long.class)))), Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
break;
case TIME_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIME_WITH_LOCAL_TIME_ZONE_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method, Expressions.call(BuiltInMethod.UNIX_DATE_TO_STRING.method, Expressions.call(BuiltInMethod.CURRENT_DATE.method, root)), operand));
break;
case TIMESTAMP:
convert = Expressions.call(BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method, RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method, operand)), Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
}
break;
case BOOLEAN:
switch(sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
convert = Expressions.call(BuiltInMethod.STRING_TO_BOOLEAN.method, operand);
}
break;
case CHAR:
case VARCHAR:
final SqlIntervalQualifier interval = sourceType.getIntervalQualifier();
switch(sourceType.getSqlTypeName()) {
case DATE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.UNIX_DATE_TO_STRING.method, operand));
break;
case TIME:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.UNIX_TIME_TO_STRING.method, operand));
break;
case TIME_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIME_WITH_LOCAL_TIME_ZONE_TO_STRING.method, operand, Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
case TIMESTAMP:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method, operand));
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_STRING.method, operand, Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.INTERVAL_YEAR_MONTH_TO_STRING.method, operand, Expressions.constant(interval.timeUnitRange)));
break;
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_SECOND:
case INTERVAL_HOUR:
case INTERVAL_HOUR_MINUTE:
case INTERVAL_HOUR_SECOND:
case INTERVAL_MINUTE:
case INTERVAL_MINUTE_SECOND:
case INTERVAL_SECOND:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.INTERVAL_DAY_TIME_TO_STRING.method, operand, Expressions.constant(interval.timeUnitRange), Expressions.constant(interval.getFractionalSecondPrecision(typeFactory.getTypeSystem()))));
break;
case BOOLEAN:
convert = RexImpTable.optimize2(operand, Expressions.call(BuiltInMethod.BOOLEAN_TO_STRING.method, operand));
break;
}
}
if (convert == null) {
convert = convert(operand, typeFactory.getJavaClass(targetType));
}
// Going from anything to CHAR(n) or VARCHAR(n), make sure value is no
// longer than n.
boolean pad = false;
boolean truncate = true;
switch(targetType.getSqlTypeName()) {
case CHAR:
case BINARY:
pad = true;
// fall through
case VARCHAR:
case VARBINARY:
final int targetPrecision = targetType.getPrecision();
if (targetPrecision >= 0) {
switch(sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
case BINARY:
case VARBINARY:
// If this is a widening cast, no need to truncate.
final int sourcePrecision = sourceType.getPrecision();
if (SqlTypeUtil.comparePrecision(sourcePrecision, targetPrecision) <= 0) {
truncate = false;
}
// If this is a widening cast, no need to pad.
if (SqlTypeUtil.comparePrecision(sourcePrecision, targetPrecision) >= 0 && targetPrecision != RelDataType.PRECISION_NOT_SPECIFIED) {
pad = false;
}
// fall through
default:
if (truncate || pad) {
convert = Expressions.call(pad ? BuiltInMethod.TRUNCATE_OR_PAD.method : BuiltInMethod.TRUNCATE.method, convert, Expressions.constant(targetPrecision));
}
}
}
break;
case TIMESTAMP:
int targetScale = targetType.getScale();
if (targetScale == RelDataType.SCALE_NOT_SPECIFIED) {
targetScale = 0;
}
if (targetScale < sourceType.getScale()) {
convert = Expressions.call(BuiltInMethod.ROUND_LONG.method, convert, Expressions.constant((long) Math.pow(10, 3 - targetScale)));
}
break;
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_SECOND:
case INTERVAL_HOUR:
case INTERVAL_HOUR_MINUTE:
case INTERVAL_HOUR_SECOND:
case INTERVAL_MINUTE:
case INTERVAL_MINUTE_SECOND:
case INTERVAL_SECOND:
switch(sourceType.getSqlTypeName().getFamily()) {
case NUMERIC:
final BigDecimal multiplier = targetType.getSqlTypeName().getEndUnit().multiplier;
final BigDecimal divider = BigDecimal.ONE;
convert = RexImpTable.multiplyDivide(convert, multiplier, divider);
}
}
return convert;
}
use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class StrictAggImplementor method implementResult.
public final Expression implementResult(AggContext info, final AggResultContext result) {
if (!needTrackEmptySet) {
return RexToLixTranslator.convert(implementNotNullResult(info, result), info.returnType());
}
String tmpName = result.accumulator().isEmpty() ? "ar" : (result.accumulator().get(0) + "$Res");
ParameterExpression res = Expressions.parameter(0, info.returnType(), result.currentBlock().newName(tmpName));
List<Expression> acc = result.accumulator();
final BlockBuilder thenBlock = result.nestBlock();
Expression nonNull = RexToLixTranslator.convert(implementNotNullResult(info, result), info.returnType());
result.exitBlock();
thenBlock.add(Expressions.statement(Expressions.assign(res, nonNull)));
BlockStatement thenBranch = thenBlock.toBlock();
Expression seenNotNullRows = trackNullsPerRow ? acc.get(acc.size() - 1) : ((WinAggResultContext) result).hasRows();
if (thenBranch.statements.size() == 1) {
return Expressions.condition(seenNotNullRows, nonNull, RexImpTable.getDefaultValue(res.getType()));
}
result.currentBlock().add(Expressions.declare(0, res, null));
result.currentBlock().add(Expressions.ifThenElse(seenNotNullRows, thenBranch, Expressions.statement(Expressions.assign(res, RexImpTable.getDefaultValue(res.getType())))));
return res;
}
Aggregations