Search in sources :

Example 26 with SpecialFormExpression

use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.

the class PageFunctionCompiler method compileProjectionInternal.

private Supplier<PageProjection> compileProjectionInternal(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, List<RowExpression> projections, boolean isOptimizeCommonSubExpression, Optional<String> classNameSuffix) {
    requireNonNull(projections, "projections is null");
    checkArgument(!projections.isEmpty() && projections.stream().allMatch(projection -> projection instanceof CallExpression || projection instanceof SpecialFormExpression));
    PageFieldsToInputParametersRewriter.Result result = rewritePageFieldsToInputParameters(projections);
    List<RowExpression> rewrittenExpression = result.getRewrittenExpressions();
    CallSiteBinder callSiteBinder = new CallSiteBinder();
    // generate Work
    ClassDefinition pageProjectionWorkDefinition = definePageProjectWorkClass(sqlFunctionProperties, sessionFunctions, rewrittenExpression, callSiteBinder, isOptimizeCommonSubExpression, classNameSuffix);
    Class<? extends Work> pageProjectionWorkClass;
    try {
        pageProjectionWorkClass = defineClass(pageProjectionWorkDefinition, Work.class, callSiteBinder.getBindings(), getClass().getClassLoader());
    } catch (PrestoException prestoException) {
        throw prestoException;
    } catch (Exception e) {
        throw new PrestoException(COMPILER_ERROR, e);
    }
    return () -> new GeneratedPageProjection(rewrittenExpression, rewrittenExpression.stream().allMatch(determinismEvaluator::isDeterministic), result.getInputChannels(), constructorMethodHandle(pageProjectionWorkClass, List.class, SqlFunctionProperties.class, Page.class, SelectedPositions.class));
}
Also used : SqlFunctionProperties(com.facebook.presto.common.function.SqlFunctionProperties) RowExpression(com.facebook.presto.spi.relation.RowExpression) PrestoException(com.facebook.presto.spi.PrestoException) GeneratedPageProjection(com.facebook.presto.operator.project.GeneratedPageProjection) Page(com.facebook.presto.common.Page) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) PrestoException(com.facebook.presto.spi.PrestoException) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) PageFieldsToInputParametersRewriter(com.facebook.presto.operator.project.PageFieldsToInputParametersRewriter) CallSiteBinder(com.facebook.presto.bytecode.CallSiteBinder) SelectedPositions(com.facebook.presto.operator.project.SelectedPositions) Work(com.facebook.presto.operator.Work) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression)

Example 27 with SpecialFormExpression

use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.

the class LambdaBytecodeGenerator method variableReferenceCompiler.

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

        @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 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));
        }

        @Override
        public BytecodeNode visitSpecialForm(SpecialFormExpression specialForm, Scope context) {
            throw new UnsupportedOperationException();
        }
    };
}
Also used : InputReferenceExpression(com.facebook.presto.spi.relation.InputReferenceExpression) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Scope(com.facebook.presto.bytecode.Scope) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) RowExpressionVisitor(com.facebook.presto.spi.relation.RowExpressionVisitor) Parameter(com.facebook.presto.bytecode.Parameter) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) LambdaDefinitionExpression(com.facebook.presto.spi.relation.LambdaDefinitionExpression)

Example 28 with SpecialFormExpression

use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.

the class SwitchCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
    Scope scope = generatorContext.getScope();
    BytecodeNode elseValue;
    List<RowExpression> whenClauses;
    RowExpression last = arguments.get(arguments.size() - 1);
    if (last instanceof SpecialFormExpression && ((SpecialFormExpression) last).getForm().equals(WHEN)) {
        whenClauses = arguments.subList(1, arguments.size());
        elseValue = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pushJavaDefault(returnType.getJavaType());
    } else {
        whenClauses = arguments.subList(1, arguments.size() - 1);
        elseValue = generatorContext.generate(last, Optional.empty());
    }
    // determine the type of the value and result
    RowExpression value = arguments.get(0);
    Class<?> valueType = value.getType().getJavaType();
    // We generate SearchedCase as CASE TRUE WHEN p1 THEN v1 WHEN p2 THEN p2...
    boolean searchedCase = (value instanceof ConstantExpression && ((ConstantExpression) value).getType() == BOOLEAN && ((ConstantExpression) value).getValue() == Boolean.TRUE);
    // evaluate the value and store it in a variable
    LabelNode elseLabel = new LabelNode("else");
    LabelNode endLabel = new LabelNode("end");
    BytecodeBlock block = new BytecodeBlock();
    Optional<BytecodeNode> getTempVariableNode;
    if (!searchedCase) {
        BytecodeNode valueBytecode = generatorContext.generate(value, Optional.empty());
        Variable tempVariable = scope.createTempVariable(valueType);
        block.append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, elseLabel, void.class, valueType)).putVariable(tempVariable);
        getTempVariableNode = Optional.of(VariableInstruction.loadVariable(tempVariable));
    } else {
        getTempVariableNode = Optional.empty();
    }
    Variable wasNull = generatorContext.wasNull();
    block.putVariable(wasNull, false);
    Map<RowExpression, LabelNode> resultLabels = new HashMap<>();
    // We already know the P1 .. Pn are all boolean just call them and search for true (false/null don't matter).
    for (RowExpression clause : whenClauses) {
        checkArgument(clause instanceof SpecialFormExpression && ((SpecialFormExpression) clause).getForm().equals(WHEN));
        RowExpression operand = ((SpecialFormExpression) clause).getArguments().get(0);
        BytecodeNode operandBytecode;
        if (searchedCase) {
            operandBytecode = generatorContext.generate(operand, Optional.empty());
        } else {
            // call equals(value, operandBytecode)
            FunctionHandle equalsFunction = generatorContext.getFunctionManager().resolveOperator(EQUAL, fromTypes(value.getType(), operand.getType()));
            operandBytecode = generatorContext.generateCall(EQUAL.name(), generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(equalsFunction), ImmutableList.of(generatorContext.generate(operand, Optional.empty()), getTempVariableNode.get()));
        }
        block.append(operandBytecode);
        IfStatement ifWasNull = new IfStatement().condition(wasNull);
        ifWasNull.ifTrue().putVariable(wasNull, false).pop(// pop the result of the predicate eval
        Boolean.class);
        // Here the TOS  is the result of the predicate.
        RowExpression result = ((SpecialFormExpression) clause).getArguments().get(1);
        LabelNode target = resultLabels.get(result);
        if (target == null) {
            target = new LabelNode(RESULT_LABEL_PREFIX + resultLabels.size());
            resultLabels.put(result, target);
        }
        ifWasNull.ifFalse().ifTrueGoto(target);
        block.append(ifWasNull);
    }
    // Here we evaluate the else result.
    block.visitLabel(elseLabel).append(elseValue).gotoLabel(endLabel);
    // Now generate the result expression code.
    for (Map.Entry<RowExpression, LabelNode> resultLabel : resultLabels.entrySet()) {
        block.visitLabel(resultLabel.getValue()).append(generatorContext.generate(resultLabel.getKey(), Optional.empty())).gotoLabel(endLabel);
    }
    block.visitLabel(endLabel);
    outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) Variable(com.facebook.presto.bytecode.Variable) HashMap(java.util.HashMap) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Scope(com.facebook.presto.bytecode.Scope) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle) HashMap(java.util.HashMap) Map(java.util.Map)

Example 29 with SpecialFormExpression

use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.

the class SubfieldExtractor method toSubfield.

private static Optional<Subfield> toSubfield(RowExpression expression, StandardFunctionResolution functionResolution, ExpressionOptimizer expressionOptimizer, ConnectorSession connectorSession) {
    List<Subfield.PathElement> elements = new ArrayList<>();
    while (true) {
        if (expression instanceof VariableReferenceExpression) {
            Collections.reverse(elements);
            return Optional.of(new Subfield(((VariableReferenceExpression) expression).getName(), unmodifiableList(elements)));
        }
        if (expression instanceof SpecialFormExpression && ((SpecialFormExpression) expression).getForm() == DEREFERENCE) {
            SpecialFormExpression dereferenceExpression = (SpecialFormExpression) expression;
            RowExpression base = dereferenceExpression.getArguments().get(0);
            RowType baseType = (RowType) base.getType();
            RowExpression indexExpression = expressionOptimizer.optimize(dereferenceExpression.getArguments().get(1), ExpressionOptimizer.Level.OPTIMIZED, connectorSession);
            if (indexExpression instanceof ConstantExpression) {
                Object index = ((ConstantExpression) indexExpression).getValue();
                if (index instanceof Number) {
                    Optional<String> fieldName = baseType.getFields().get(((Number) index).intValue()).getName();
                    if (fieldName.isPresent()) {
                        elements.add(new Subfield.NestedField(fieldName.get()));
                        expression = base;
                        continue;
                    }
                }
            }
            return Optional.empty();
        }
        if (expression instanceof CallExpression && functionResolution.isSubscriptFunction(((CallExpression) expression).getFunctionHandle())) {
            List<RowExpression> arguments = ((CallExpression) expression).getArguments();
            RowExpression indexExpression = expressionOptimizer.optimize(arguments.get(1), ExpressionOptimizer.Level.OPTIMIZED, connectorSession);
            if (indexExpression instanceof ConstantExpression) {
                Object index = ((ConstantExpression) indexExpression).getValue();
                if (index instanceof Number) {
                    elements.add(new Subfield.LongSubscript(((Number) index).longValue()));
                    expression = arguments.get(0);
                    continue;
                }
                if (isVarcharType(indexExpression.getType())) {
                    elements.add(new Subfield.StringSubscript(((Slice) index).toStringUtf8()));
                    expression = arguments.get(0);
                    continue;
                }
            }
            return Optional.empty();
        }
        return Optional.empty();
    }
}
Also used : ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) ArrayList(java.util.ArrayList) RowExpression(com.facebook.presto.spi.relation.RowExpression) RowType(com.facebook.presto.common.type.RowType) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) Slice(io.airlift.slice.Slice) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) CallExpression(com.facebook.presto.spi.relation.CallExpression) Subfield(com.facebook.presto.common.Subfield)

Example 30 with SpecialFormExpression

use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.

the class TestRowExpressionFormatter method testSpecialForm.

@Test
public void testSpecialForm() {
    RowExpression specialFormExpression;
    // or and and
    specialFormExpression = new SpecialFormExpression(OR, BOOLEAN, createCallExpression(NOT_EQUAL), createCallExpression(IS_DISTINCT_FROM));
    assertEquals(format(specialFormExpression), "((c_bigint) <> (BIGINT'5')) OR ((c_bigint) IS DISTINCT FROM (BIGINT'5'))");
    specialFormExpression = new SpecialFormExpression(AND, BOOLEAN, createCallExpression(EQUAL), createCallExpression(GREATER_THAN));
    assertEquals(format(specialFormExpression), "((c_bigint) = (BIGINT'5')) AND ((c_bigint) > (BIGINT'5'))");
    // other
    specialFormExpression = new SpecialFormExpression(IS_NULL, BOOLEAN, createCallExpression(ADD));
    assertEquals(format(specialFormExpression), "IS_NULL((c_bigint) + (BIGINT'5'))");
}
Also used : RowExpression(com.facebook.presto.spi.relation.RowExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) Test(org.testng.annotations.Test)

Aggregations

SpecialFormExpression (com.facebook.presto.spi.relation.SpecialFormExpression)46 RowExpression (com.facebook.presto.spi.relation.RowExpression)38 ConstantExpression (com.facebook.presto.spi.relation.ConstantExpression)18 VariableReferenceExpression (com.facebook.presto.spi.relation.VariableReferenceExpression)18 CallExpression (com.facebook.presto.spi.relation.CallExpression)16 ImmutableList (com.google.common.collect.ImmutableList)14 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)12 Test (org.testng.annotations.Test)12 Variable (com.facebook.presto.bytecode.Variable)10 Type (com.facebook.presto.common.type.Type)10 IfStatement (com.facebook.presto.bytecode.control.IfStatement)8 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)8 Page (com.facebook.presto.common.Page)8 RowType (com.facebook.presto.common.type.RowType)8 Scope (com.facebook.presto.bytecode.Scope)6 Subfield (com.facebook.presto.common.Subfield)6 ArrayDeque (java.util.ArrayDeque)6 ArrayList (java.util.ArrayList)6 Map (java.util.Map)6 LambdaDefinitionExpression (com.facebook.presto.spi.relation.LambdaDefinitionExpression)5