Search in sources :

Example 26 with Type

use of io.trino.spi.type.Type in project trino by trinodb.

the class ExpressionInterpreter method evaluateConstantExpression.

public static Object evaluateConstantExpression(Expression expression, Type expectedType, PlannerContext plannerContext, Session session, AccessControl accessControl, Map<NodeRef<Parameter>, Expression> parameters) {
    ExpressionAnalyzer analyzer = createConstantAnalyzer(plannerContext, accessControl, session, parameters, WarningCollector.NOOP);
    analyzer.analyze(expression, Scope.create());
    Type actualType = analyzer.getExpressionTypes().get(NodeRef.of(expression));
    if (!new TypeCoercion(plannerContext.getTypeManager()::getType).canCoerce(actualType, expectedType)) {
        throw semanticException(TYPE_MISMATCH, expression, "Cannot cast type %s to %s", actualType.getDisplayName(), expectedType.getDisplayName());
    }
    Map<NodeRef<Expression>, Type> coercions = ImmutableMap.<NodeRef<Expression>, Type>builder().putAll(analyzer.getExpressionCoercions()).put(NodeRef.of(expression), expectedType).buildOrThrow();
    return evaluateConstantExpression(expression, coercions, analyzer.getTypeOnlyCoercions(), plannerContext, session, accessControl, ImmutableSet.of(), parameters);
}
Also used : NodeRef(io.trino.sql.tree.NodeRef) FunctionType(io.trino.type.FunctionType) OperatorType(io.trino.spi.function.OperatorType) CharType(io.trino.spi.type.CharType) VarcharType.createVarcharType(io.trino.spi.type.VarcharType.createVarcharType) RowType(io.trino.spi.type.RowType) TypeSignatureTranslator.toSqlType(io.trino.sql.analyzer.TypeSignatureTranslator.toSqlType) ArrayType(io.trino.spi.type.ArrayType) Type(io.trino.spi.type.Type) VarcharType(io.trino.spi.type.VarcharType) NullIfExpression(io.trino.sql.tree.NullIfExpression) ArithmeticUnaryExpression(io.trino.sql.tree.ArithmeticUnaryExpression) DereferenceExpression(io.trino.sql.tree.DereferenceExpression) InListExpression(io.trino.sql.tree.InListExpression) NotExpression(io.trino.sql.tree.NotExpression) ArithmeticBinaryExpression(io.trino.sql.tree.ArithmeticBinaryExpression) LogicalExpression(io.trino.sql.tree.LogicalExpression) SearchedCaseExpression(io.trino.sql.tree.SearchedCaseExpression) BindExpression(io.trino.sql.tree.BindExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) IfExpression(io.trino.sql.tree.IfExpression) QuantifiedComparisonExpression(io.trino.sql.tree.QuantifiedComparisonExpression) Expression(io.trino.sql.tree.Expression) SimpleCaseExpression(io.trino.sql.tree.SimpleCaseExpression) SubqueryExpression(io.trino.sql.tree.SubqueryExpression) LambdaExpression(io.trino.sql.tree.LambdaExpression) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) CanonicalizeExpressionRewriter.canonicalizeExpression(io.trino.sql.planner.iterative.rule.CanonicalizeExpressionRewriter.canonicalizeExpression) ExpressionAnalyzer(io.trino.sql.analyzer.ExpressionAnalyzer) TypeCoercion(io.trino.type.TypeCoercion)

Example 27 with Type

use of io.trino.spi.type.Type in project trino by trinodb.

the class CursorProcessorCompiler method fieldReferenceCompiler.

private static RowExpressionVisitor<BytecodeNode, Scope> fieldReferenceCompiler(Variable cursorVariable) {
    return new RowExpressionVisitor<>() {

        @Override
        public BytecodeNode visitInputReference(InputReferenceExpression node, Scope scope) {
            int field = node.getField();
            Type type = node.getType();
            Variable wasNullVariable = scope.getVariable("wasNull");
            Class<?> javaType = type.getJavaType();
            IfStatement ifStatement = new IfStatement();
            ifStatement.condition().setDescription(format("cursor.get%s(%d)", type, field)).getVariable(cursorVariable).push(field).invokeInterface(RecordCursor.class, "isNull", boolean.class, int.class);
            ifStatement.ifTrue().putVariable(wasNullVariable, true).pushJavaDefault(javaType);
            ifStatement.ifFalse().getVariable(cursorVariable).push(field);
            if (javaType == boolean.class) {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getBoolean", boolean.class, int.class);
            } else if (javaType == long.class) {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getLong", long.class, int.class);
            } else if (javaType == double.class) {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getDouble", double.class, int.class);
            } else if (javaType == Slice.class) {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getSlice", Slice.class, int.class);
            } else {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getObject", Object.class, int.class).checkCast(javaType);
            }
            return ifStatement;
        }

        @Override
        public BytecodeNode visitCall(CallExpression call, Scope scope) {
            throw new UnsupportedOperationException("not yet implemented");
        }

        @Override
        public BytecodeNode visitSpecialForm(SpecialForm specialForm, Scope context) {
            throw new UnsupportedOperationException("not yet implemented");
        }

        @Override
        public BytecodeNode visitConstant(ConstantExpression literal, Scope scope) {
            throw new UnsupportedOperationException("not yet implemented");
        }

        @Override
        public BytecodeNode visitLambda(LambdaDefinitionExpression lambda, Scope context) {
            throw new UnsupportedOperationException();
        }

        @Override
        public BytecodeNode visitVariableReference(VariableReferenceExpression reference, Scope context) {
            throw new UnsupportedOperationException();
        }
    };
}
Also used : InputReferenceExpression(io.trino.sql.relational.InputReferenceExpression) Variable(io.airlift.bytecode.Variable) RecordCursor(io.trino.spi.connector.RecordCursor) ConstantExpression(io.trino.sql.relational.ConstantExpression) IfStatement(io.airlift.bytecode.control.IfStatement) Type(io.trino.spi.type.Type) Scope(io.airlift.bytecode.Scope) Slice(io.airlift.slice.Slice) VariableReferenceExpression(io.trino.sql.relational.VariableReferenceExpression) RowExpressionVisitor(io.trino.sql.relational.RowExpressionVisitor) CallExpression(io.trino.sql.relational.CallExpression) SpecialForm(io.trino.sql.relational.SpecialForm) LambdaDefinitionExpression(io.trino.sql.relational.LambdaDefinitionExpression)

Example 28 with Type

use of io.trino.spi.type.Type in project trino by trinodb.

the class InCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext) {
    Type type = valueExpression.getType();
    Class<?> javaType = type.getJavaType();
    SwitchGenerationCase switchGenerationCase = checkSwitchGenerationCase(type, testExpressions);
    MethodHandle equalsMethodHandle = generatorContext.getScalarFunctionInvoker(resolvedEqualsFunction, simpleConvention(NULLABLE_RETURN, NEVER_NULL, NEVER_NULL)).getMethodHandle();
    MethodHandle hashCodeMethodHandle = generatorContext.getScalarFunctionInvoker(resolvedHashCodeFunction, simpleConvention(FAIL_ON_NULL, NEVER_NULL)).getMethodHandle();
    MethodHandle indeterminateMethodHandle = generatorContext.getScalarFunctionInvoker(resolvedIsIndeterminate, simpleConvention(FAIL_ON_NULL, NEVER_NULL)).getMethodHandle();
    ImmutableListMultimap.Builder<Integer, BytecodeNode> hashBucketsBuilder = ImmutableListMultimap.builder();
    ImmutableList.Builder<BytecodeNode> defaultBucket = ImmutableList.builder();
    ImmutableSet.Builder<Object> constantValuesBuilder = ImmutableSet.builder();
    for (RowExpression testValue : testExpressions) {
        BytecodeNode testBytecode = generatorContext.generate(testValue);
        if (isDeterminateConstant(testValue, indeterminateMethodHandle)) {
            ConstantExpression constant = (ConstantExpression) testValue;
            Object object = constant.getValue();
            switch(switchGenerationCase) {
                case DIRECT_SWITCH:
                case SET_CONTAINS:
                    constantValuesBuilder.add(object);
                    break;
                case HASH_SWITCH:
                    try {
                        int hashCode = Long.hashCode((Long) hashCodeMethodHandle.invoke(object));
                        hashBucketsBuilder.put(hashCode, testBytecode);
                    } catch (Throwable throwable) {
                        throw new IllegalArgumentException("Error processing IN statement: error calculating hash code for " + object, throwable);
                    }
                    break;
                default:
                    throw new IllegalArgumentException("Not supported switch generation case: " + switchGenerationCase);
            }
        } else {
            defaultBucket.add(testBytecode);
        }
    }
    ImmutableListMultimap<Integer, BytecodeNode> hashBuckets = hashBucketsBuilder.build();
    ImmutableSet<Object> constantValues = constantValuesBuilder.build();
    LabelNode end = new LabelNode("end");
    LabelNode match = new LabelNode("match");
    LabelNode noMatch = new LabelNode("noMatch");
    LabelNode defaultLabel = new LabelNode("default");
    Scope scope = generatorContext.getScope();
    Variable value = scope.createTempVariable(javaType);
    BytecodeNode switchBlock;
    Variable expression = scope.createTempVariable(int.class);
    SwitchBuilder switchBuilder = new SwitchBuilder().expression(expression);
    switch(switchGenerationCase) {
        case DIRECT_SWITCH:
            // For these types, it's safe to not use Trino HASH_CODE and EQUAL operator.
            for (Object constantValue : constantValues) {
                switchBuilder.addCase(toIntExact((Long) constantValue), jump(match));
            }
            switchBuilder.defaultCase(jump(defaultLabel));
            switchBlock = new BytecodeBlock().comment("lookupSwitch(<stackValue>))").append(new IfStatement().condition(invokeStatic(InCodeGenerator.class, "isInteger", boolean.class, value)).ifFalse(new BytecodeBlock().gotoLabel(defaultLabel))).append(expression.set(value.cast(int.class))).append(switchBuilder.build());
            break;
        case HASH_SWITCH:
            for (Map.Entry<Integer, Collection<BytecodeNode>> bucket : hashBuckets.asMap().entrySet()) {
                Collection<BytecodeNode> testValues = bucket.getValue();
                BytecodeBlock caseBlock = buildInCase(generatorContext, scope, resolvedEqualsFunction, match, defaultLabel, value, testValues, false, resolvedIsIndeterminate);
                switchBuilder.addCase(bucket.getKey(), caseBlock);
            }
            switchBuilder.defaultCase(jump(defaultLabel));
            Binding hashCodeBinding = generatorContext.getCallSiteBinder().bind(hashCodeMethodHandle);
            switchBlock = new BytecodeBlock().comment("lookupSwitch(hashCode(<stackValue>))").getVariable(value).append(invoke(hashCodeBinding, resolvedHashCodeFunction.getSignature())).invokeStatic(Long.class, "hashCode", int.class, long.class).putVariable(expression).append(switchBuilder.build());
            break;
        case SET_CONTAINS:
            Set<?> constantValuesSet = toFastutilHashSet(constantValues, type, hashCodeMethodHandle, equalsMethodHandle);
            Binding constant = generatorContext.getCallSiteBinder().bind(constantValuesSet, constantValuesSet.getClass());
            switchBlock = new BytecodeBlock().comment("inListSet.contains(<stackValue>)").append(new IfStatement().condition(new BytecodeBlock().comment("value").getVariable(value).comment("set").append(loadConstant(constant)).invokeStatic(FastutilSetHelper.class, "in", boolean.class, javaType.isPrimitive() ? javaType : Object.class, constantValuesSet.getClass())).ifTrue(jump(match)));
            break;
        default:
            throw new IllegalArgumentException("Not supported switch generation case: " + switchGenerationCase);
    }
    BytecodeBlock defaultCaseBlock = buildInCase(generatorContext, scope, resolvedEqualsFunction, match, noMatch, value, defaultBucket.build(), true, resolvedIsIndeterminate).setDescription("default");
    BytecodeBlock block = new BytecodeBlock().comment("IN").append(generatorContext.generate(valueExpression)).append(ifWasNullPopAndGoto(scope, end, boolean.class, javaType)).putVariable(value).append(switchBlock).visitLabel(defaultLabel).append(defaultCaseBlock);
    BytecodeBlock matchBlock = new BytecodeBlock().setDescription("match").visitLabel(match).append(generatorContext.wasNull().set(constantFalse())).push(true).gotoLabel(end);
    block.append(matchBlock);
    BytecodeBlock noMatchBlock = new BytecodeBlock().setDescription("noMatch").visitLabel(noMatch).push(false).gotoLabel(end);
    block.append(noMatchBlock);
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) Variable(io.airlift.bytecode.Variable) ImmutableList(com.google.common.collect.ImmutableList) ConstantExpression(io.trino.sql.relational.ConstantExpression) IfStatement(io.airlift.bytecode.control.IfStatement) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) BytecodeNode(io.airlift.bytecode.BytecodeNode) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) RowExpression(io.trino.sql.relational.RowExpression) Type(io.trino.spi.type.Type) Scope(io.airlift.bytecode.Scope) SwitchBuilder(io.airlift.bytecode.control.SwitchStatement.SwitchBuilder) Collection(java.util.Collection) Map(java.util.Map) MethodHandle(java.lang.invoke.MethodHandle)

Example 29 with Type

use of io.trino.spi.type.Type in project trino by trinodb.

the class InputReferenceCompiler method visitInputReference.

@Override
public BytecodeNode visitInputReference(InputReferenceExpression node, Scope scope) {
    int field = node.getField();
    Type type = node.getType();
    BytecodeExpression block = blockResolver.apply(scope, field);
    BytecodeExpression position = positionResolver.apply(scope, field);
    return generateInputReference(callSiteBinder, scope, type, block, position);
}
Also used : Type(io.trino.spi.type.Type) SqlTypeBytecodeExpression.constantType(io.trino.sql.gen.SqlTypeBytecodeExpression.constantType) BytecodeExpression(io.airlift.bytecode.expression.BytecodeExpression)

Example 30 with Type

use of io.trino.spi.type.Type in project trino by trinodb.

the class JoinCompiler method generatePositionEqualsRowMethod.

private void generatePositionEqualsRowMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> joinChannelTypes, List<FieldDefinition> joinChannelFields, boolean ignoreNulls) {
    Parameter leftBlockIndex = arg("leftBlockIndex", int.class);
    Parameter leftBlockPosition = arg("leftBlockPosition", int.class);
    Parameter rightPosition = arg("rightPosition", int.class);
    Parameter rightPage = arg("rightPage", Page.class);
    MethodDefinition positionEqualsRowMethod = classDefinition.declareMethod(a(PUBLIC), ignoreNulls ? "positionEqualsRowIgnoreNulls" : "positionEqualsRow", type(boolean.class), leftBlockIndex, leftBlockPosition, rightPosition, rightPage);
    Variable thisVariable = positionEqualsRowMethod.getThis();
    for (int index = 0; index < joinChannelTypes.size(); index++) {
        Type type = joinChannelTypes.get(index);
        BytecodeExpression leftBlock = thisVariable.getField(joinChannelFields.get(index)).invoke("get", Object.class, leftBlockIndex).cast(Block.class);
        BytecodeExpression rightBlock = rightPage.invoke("getBlock", Block.class, constantInt(index));
        BytecodeNode equalityCondition;
        if (ignoreNulls) {
            equalityCondition = typeEqualsIgnoreNulls(callSiteBinder, type, leftBlock, leftBlockPosition, rightBlock, rightPosition);
        } else {
            equalityCondition = typeEquals(callSiteBinder, type, leftBlock, leftBlockPosition, rightBlock, rightPosition);
        }
        LabelNode checkNextField = new LabelNode("checkNextField");
        positionEqualsRowMethod.getBody().append(equalityCondition).ifTrueGoto(checkNextField).push(false).retBoolean().visitLabel(checkNextField);
    }
    positionEqualsRowMethod.getBody().push(true).retInt();
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) SqlTypeBytecodeExpression.constantType(io.trino.sql.gen.SqlTypeBytecodeExpression.constantType) Type(io.trino.spi.type.Type) BigintType(io.trino.spi.type.BigintType) Variable(io.airlift.bytecode.Variable) MethodDefinition(io.airlift.bytecode.MethodDefinition) Parameter(io.airlift.bytecode.Parameter) BytecodeNode(io.airlift.bytecode.BytecodeNode) BytecodeExpression(io.airlift.bytecode.expression.BytecodeExpression)

Aggregations

Type (io.trino.spi.type.Type)688 Test (org.testng.annotations.Test)266 ArrayType (io.trino.spi.type.ArrayType)218 ImmutableList (com.google.common.collect.ImmutableList)191 RowType (io.trino.spi.type.RowType)177 List (java.util.List)155 VarcharType (io.trino.spi.type.VarcharType)134 Page (io.trino.spi.Page)126 ArrayList (java.util.ArrayList)126 VarcharType.createUnboundedVarcharType (io.trino.spi.type.VarcharType.createUnboundedVarcharType)114 Block (io.trino.spi.block.Block)110 MapType (io.trino.spi.type.MapType)107 DecimalType (io.trino.spi.type.DecimalType)102 TrinoException (io.trino.spi.TrinoException)98 Optional (java.util.Optional)98 Map (java.util.Map)97 ImmutableMap (com.google.common.collect.ImmutableMap)93 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)92 DecimalType.createDecimalType (io.trino.spi.type.DecimalType.createDecimalType)86 BlockBuilder (io.trino.spi.block.BlockBuilder)72