Search in sources :

Example 16 with Expression

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);
}
Also used : UnaryExpression(org.apache.calcite.linq4j.tree.UnaryExpression) ConstantExpression(org.apache.calcite.linq4j.tree.ConstantExpression) ParameterExpression(org.apache.calcite.linq4j.tree.ParameterExpression) Expression(org.apache.calcite.linq4j.tree.Expression) MemberExpression(org.apache.calcite.linq4j.tree.MemberExpression) RexNode(org.apache.calcite.rex.RexNode)

Example 17 with Expression

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);
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexCorrelVariable(org.apache.calcite.rex.RexCorrelVariable) Expression(org.apache.calcite.linq4j.tree.Expression) UnaryExpression(org.apache.calcite.linq4j.tree.UnaryExpression) ConstantExpression(org.apache.calcite.linq4j.tree.ConstantExpression) ParameterExpression(org.apache.calcite.linq4j.tree.ParameterExpression) RexInputRef(org.apache.calcite.rex.RexInputRef) RexFieldAccess(org.apache.calcite.rex.RexFieldAccess) RexNode(org.apache.calcite.rex.RexNode)

Example 18 with Expression

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);
    }
}
Also used : Expression(org.apache.calcite.linq4j.tree.Expression) UnaryExpression(org.apache.calcite.linq4j.tree.UnaryExpression) ConstantExpression(org.apache.calcite.linq4j.tree.ConstantExpression) ParameterExpression(org.apache.calcite.linq4j.tree.ParameterExpression) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) RexNode(org.apache.calcite.rex.RexNode)

Example 19 with Expression

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;
}
Also used : Expression(org.apache.calcite.linq4j.tree.Expression) UnaryExpression(org.apache.calcite.linq4j.tree.UnaryExpression) ConstantExpression(org.apache.calcite.linq4j.tree.ConstantExpression) ParameterExpression(org.apache.calcite.linq4j.tree.ParameterExpression) SqlIntervalQualifier(org.apache.calcite.sql.SqlIntervalQualifier) BigDecimal(java.math.BigDecimal)

Example 20 with Expression

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;
}
Also used : Expression(org.apache.calcite.linq4j.tree.Expression) ParameterExpression(org.apache.calcite.linq4j.tree.ParameterExpression) ParameterExpression(org.apache.calcite.linq4j.tree.ParameterExpression) BlockStatement(org.apache.calcite.linq4j.tree.BlockStatement) BlockBuilder(org.apache.calcite.linq4j.tree.BlockBuilder)

Aggregations

Expression (org.apache.calcite.linq4j.tree.Expression)91 ParameterExpression (org.apache.calcite.linq4j.tree.ParameterExpression)64 BlockBuilder (org.apache.calcite.linq4j.tree.BlockBuilder)56 ArrayList (java.util.ArrayList)22 MethodCallExpression (org.apache.calcite.linq4j.tree.MethodCallExpression)19 RelDataType (org.apache.calcite.rel.type.RelDataType)19 ConstantExpression (org.apache.calcite.linq4j.tree.ConstantExpression)16 Test (org.junit.Test)16 Type (java.lang.reflect.Type)11 PhysType (org.apache.calcite.adapter.enumerable.PhysType)11 UnaryExpression (org.apache.calcite.linq4j.tree.UnaryExpression)11 RexNode (org.apache.calcite.rex.RexNode)10 JavaTypeFactory (org.apache.calcite.adapter.java.JavaTypeFactory)9 BinaryExpression (org.apache.calcite.linq4j.tree.BinaryExpression)8 BlockStatement (org.apache.calcite.linq4j.tree.BlockStatement)8 NewExpression (org.apache.calcite.linq4j.tree.NewExpression)8 FunctionExpression (org.apache.calcite.linq4j.tree.FunctionExpression)7 MemberDeclaration (org.apache.calcite.linq4j.tree.MemberDeclaration)7 ImmutableList (com.google.common.collect.ImmutableList)5 List (java.util.List)5