use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class RexImpTable method createImplementor.
public static CallImplementor createImplementor(final NotNullImplementor implementor, final NullPolicy nullPolicy, final boolean harmonize) {
switch(nullPolicy) {
case ANY:
case STRICT:
case SEMI_STRICT:
return new CallImplementor() {
public Expression implement(RexToLixTranslator translator, RexCall call, NullAs nullAs) {
return implementNullSemantics0(translator, call, nullAs, nullPolicy, harmonize, implementor);
}
};
case AND:
// : Boolean.FALSE;
return new CallImplementor() {
public Expression implement(RexToLixTranslator translator, RexCall call, NullAs nullAs) {
assert call.getOperator() == AND : "AND null semantics is supported only for AND operator. Actual operator is " + String.valueOf(call.getOperator());
final RexCall call2 = call2(false, translator, call);
switch(nullAs) {
// Just foldAnd
case NOT_POSSIBLE:
case TRUE:
// thus if we convert nulls to true then no harm is made
case FALSE:
// AND call should return false iff has FALSEs or has NULLs,
// thus if we convert nulls to false, no harm is made
final List<Expression> expressions = translator.translateList(call2.getOperands(), nullAs);
return Expressions.foldAnd(expressions);
case NULL:
case IS_NULL:
case IS_NOT_NULL:
final List<Expression> nullAsTrue = translator.translateList(call2.getOperands(), NullAs.TRUE);
final List<Expression> nullAsIsNull = translator.translateList(call2.getOperands(), NullAs.IS_NULL);
Expression hasFalse = Expressions.not(Expressions.foldAnd(nullAsTrue));
Expression hasNull = Expressions.foldOr(nullAsIsNull);
Expression result = nullAs.handle(Expressions.condition(hasFalse, BOXED_FALSE_EXPR, Expressions.condition(hasNull, NULL_EXPR, BOXED_TRUE_EXPR)));
return result;
default:
throw new IllegalArgumentException("Unknown nullAs when implementing AND: " + nullAs);
}
}
};
case OR:
// : Boolean.TRUE;
return new CallImplementor() {
public Expression implement(RexToLixTranslator translator, RexCall call, final NullAs nullAs) {
assert call.getOperator() == OR : "OR null semantics is supported only for OR operator. Actual operator is " + String.valueOf(call.getOperator());
final RexCall call2 = call2(harmonize, translator, call);
switch(nullAs) {
// Just foldOr
case NOT_POSSIBLE:
case TRUE:
// thus we convert nulls to TRUE and foldOr
case FALSE:
// This should return true iff has TRUE arguments,
// thus we convert nulls to FALSE and foldOr
final List<Expression> expressions = translator.translateList(call2.getOperands(), nullAs);
return Expressions.foldOr(expressions);
case NULL:
case IS_NULL:
case IS_NOT_NULL:
final List<Expression> nullAsFalse = translator.translateList(call2.getOperands(), NullAs.FALSE);
final List<Expression> nullAsIsNull = translator.translateList(call2.getOperands(), NullAs.IS_NULL);
Expression hasTrue = Expressions.foldOr(nullAsFalse);
Expression hasNull = Expressions.foldOr(nullAsIsNull);
Expression result = nullAs.handle(Expressions.condition(hasTrue, BOXED_TRUE_EXPR, Expressions.condition(hasNull, NULL_EXPR, BOXED_FALSE_EXPR)));
return result;
default:
throw new IllegalArgumentException("Unknown nullAs when implementing OR: " + nullAs);
}
}
};
case NOT:
// else false.
return new CallImplementor() {
public Expression implement(RexToLixTranslator translator, RexCall call, NullAs nullAs) {
switch(nullAs) {
case NULL:
return Expressions.call(BuiltInMethod.NOT.method, translator.translateList(call.getOperands(), nullAs));
default:
return Expressions.not(translator.translate(call.getOperands().get(0), negate(nullAs)));
}
}
private NullAs negate(NullAs nullAs) {
switch(nullAs) {
case FALSE:
return NullAs.TRUE;
case TRUE:
return NullAs.FALSE;
default:
return nullAs;
}
}
};
case NONE:
return new CallImplementor() {
public Expression implement(RexToLixTranslator translator, RexCall call, NullAs nullAs) {
final RexCall call2 = call2(false, translator, call);
return implementCall(translator, call2, implementor, nullAs);
}
};
default:
throw new AssertionError(nullPolicy);
}
}
use of org.apache.beam.vendor.calcite.v1_28_0.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.beam.vendor.calcite.v1_28_0.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.beam.vendor.calcite.v1_28_0.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.beam.vendor.calcite.v1_28_0.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;
}
Aggregations