Search in sources :

Example 1 with SpecialForm

use of io.trino.sql.relational.SpecialForm 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 2 with SpecialForm

use of io.trino.sql.relational.SpecialForm in project trino by trinodb.

the class LambdaBytecodeGenerator method variableReferenceCompiler.

private static RowExpressionVisitor<BytecodeNode, Scope> variableReferenceCompiler(Map<String, ParameterAndType> parameterMap) {
    return new RowExpressionVisitor<>() {

        @Override
        public BytecodeNode visitInputReference(InputReferenceExpression node, Scope scope) {
            throw new UnsupportedOperationException();
        }

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

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

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

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

        @Override
        public BytecodeNode visitVariableReference(VariableReferenceExpression reference, Scope context) {
            ParameterAndType parameterAndType = parameterMap.get(reference.getName());
            Parameter parameter = parameterAndType.getParameter();
            Class<?> type = parameterAndType.getType();
            return new BytecodeBlock().append(parameter).append(unboxPrimitiveIfNecessary(context, type));
        }
    };
}
Also used : InputReferenceExpression(io.trino.sql.relational.InputReferenceExpression) ConstantExpression(io.trino.sql.relational.ConstantExpression) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) Scope(io.airlift.bytecode.Scope) VariableReferenceExpression(io.trino.sql.relational.VariableReferenceExpression) RowExpressionVisitor(io.trino.sql.relational.RowExpressionVisitor) Parameter(io.airlift.bytecode.Parameter) CallExpression(io.trino.sql.relational.CallExpression) SpecialForm(io.trino.sql.relational.SpecialForm) LambdaDefinitionExpression(io.trino.sql.relational.LambdaDefinitionExpression)

Example 3 with SpecialForm

use of io.trino.sql.relational.SpecialForm in project trino by trinodb.

the class SwitchCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext) {
    // TODO: compile as
    /*
            hashCode = hashCode(<value>)

            // all constant expressions before a non-constant
            switch (hashCode) {
                case ...:
                    if (<value> == <constant1>) {
                       ...
                    }
                    else if (<value> == <constant2>) {
                       ...
                    }
                    else if (...) {
                    }
                case ...:
                    ...
            }

            if (<value> == <non-constant1>) {
                ...
            }
            else if (<value> == <non-constant2>) {
                ...
            }
            ...

            // repeat with next sequence of constant expressions
         */
    Scope scope = generatorContext.getScope();
    // process value, else, and all when clauses
    BytecodeNode valueBytecode = generatorContext.generate(value);
    BytecodeNode elseValue;
    if (this.elseValue.isEmpty()) {
        elseValue = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pushJavaDefault(returnType.getJavaType());
    } else {
        elseValue = generatorContext.generate(this.elseValue.get());
    }
    // determine the type of the value and result
    Class<?> valueType = value.getType().getJavaType();
    // evaluate the value and store it in a variable
    LabelNode nullValue = new LabelNode("nullCondition");
    Variable tempVariable = scope.createTempVariable(valueType);
    BytecodeBlock block = new BytecodeBlock().append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, nullValue, void.class, valueType)).putVariable(tempVariable);
    BytecodeNode getTempVariableNode = VariableInstruction.loadVariable(tempVariable);
    // build the statements
    elseValue = new BytecodeBlock().visitLabel(nullValue).append(elseValue);
    // reverse list because current if statement builder doesn't support if/else so we need to build the if statements bottom up
    for (int i = whenClauses.size() - 1; i >= 0; i--) {
        SpecialForm clause = whenClauses.get(i);
        RowExpression operand = clause.getArguments().get(0);
        RowExpression result = clause.getArguments().get(1);
        // call equals(value, operand)
        // TODO: what if operand is null? It seems that the call will return "null" (which is cleared below)
        // and the code only does the right thing because the value in the stack for that scenario is
        // Java's default for boolean == false
        // This code should probably be checking for wasNull after the call and "failing" the equality
        // check if wasNull is true
        BytecodeNode equalsCall = generatorContext.generateCall(equalsFunctions.get(i), ImmutableList.of(generatorContext.generate(operand), getTempVariableNode));
        BytecodeBlock condition = new BytecodeBlock().append(equalsCall).append(generatorContext.wasNull().set(constantFalse()));
        elseValue = new IfStatement("when").condition(condition).ifTrue(generatorContext.generate(result)).ifFalse(elseValue);
    }
    return block.append(elseValue);
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) IfStatement(io.airlift.bytecode.control.IfStatement) Variable(io.airlift.bytecode.Variable) Scope(io.airlift.bytecode.Scope) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) RowExpression(io.trino.sql.relational.RowExpression) BytecodeNode(io.airlift.bytecode.BytecodeNode) SpecialForm(io.trino.sql.relational.SpecialForm)

Example 4 with SpecialForm

use of io.trino.sql.relational.SpecialForm in project trino by trinodb.

the class BetweenCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext context) {
    Variable firstValue = context.getScope().createTempVariable(value.getType().getJavaType());
    VariableReferenceExpression valueReference = createTempVariableReferenceExpression(firstValue, value.getType());
    SpecialForm newExpression = new SpecialForm(AND, BOOLEAN, call(lessThanOrEqual, min, valueReference), call(lessThanOrEqual, valueReference, max));
    LabelNode done = new LabelNode("done");
    // push value arg on the stack
    BytecodeBlock block = new BytecodeBlock().comment("check if value is null").append(context.generate(value)).append(ifWasNullPopAndGoto(context.getScope(), done, boolean.class, value.getType().getJavaType())).putVariable(firstValue).append(context.generate(newExpression)).visitLabel(done);
    return block;
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) Variable(io.airlift.bytecode.Variable) VariableReferenceExpression(io.trino.sql.relational.VariableReferenceExpression) RowExpressionCompiler.createTempVariableReferenceExpression(io.trino.sql.gen.RowExpressionCompiler.createTempVariableReferenceExpression) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) SpecialForm(io.trino.sql.relational.SpecialForm)

Aggregations

SpecialForm (io.trino.sql.relational.SpecialForm)4 BytecodeBlock (io.airlift.bytecode.BytecodeBlock)3 Scope (io.airlift.bytecode.Scope)3 Variable (io.airlift.bytecode.Variable)3 VariableReferenceExpression (io.trino.sql.relational.VariableReferenceExpression)3 IfStatement (io.airlift.bytecode.control.IfStatement)2 LabelNode (io.airlift.bytecode.instruction.LabelNode)2 CallExpression (io.trino.sql.relational.CallExpression)2 ConstantExpression (io.trino.sql.relational.ConstantExpression)2 InputReferenceExpression (io.trino.sql.relational.InputReferenceExpression)2 LambdaDefinitionExpression (io.trino.sql.relational.LambdaDefinitionExpression)2 RowExpressionVisitor (io.trino.sql.relational.RowExpressionVisitor)2 BytecodeNode (io.airlift.bytecode.BytecodeNode)1 Parameter (io.airlift.bytecode.Parameter)1 Slice (io.airlift.slice.Slice)1 RecordCursor (io.trino.spi.connector.RecordCursor)1 Type (io.trino.spi.type.Type)1 RowExpressionCompiler.createTempVariableReferenceExpression (io.trino.sql.gen.RowExpressionCompiler.createTempVariableReferenceExpression)1 RowExpression (io.trino.sql.relational.RowExpression)1