Search in sources :

Example 1 with SpecialFormExpression

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

the class SubfieldExtractor method toRowExpression.

private RowExpression toRowExpression(Subfield subfield, List<Type> types) {
    List<Subfield.PathElement> path = subfield.getPath();
    if (path.isEmpty()) {
        return new VariableReferenceExpression(Optional.empty(), subfield.getRootName(), types.get(0));
    }
    RowExpression base = toRowExpression(new Subfield(subfield.getRootName(), path.subList(0, path.size() - 1)), types.subList(0, types.size() - 1));
    Type baseType = types.get(types.size() - 2);
    Subfield.PathElement pathElement = path.get(path.size() - 1);
    if (pathElement instanceof Subfield.LongSubscript) {
        Type indexType = baseType instanceof MapType ? ((MapType) baseType).getKeyType() : BIGINT;
        FunctionHandle functionHandle = functionResolution.subscriptFunction(baseType, indexType);
        ConstantExpression index = new ConstantExpression(base.getSourceLocation(), ((Subfield.LongSubscript) pathElement).getIndex(), indexType);
        return new CallExpression(base.getSourceLocation(), SUBSCRIPT.name(), functionHandle, types.get(types.size() - 1), ImmutableList.of(base, index));
    }
    if (pathElement instanceof Subfield.StringSubscript) {
        Type indexType = ((MapType) baseType).getKeyType();
        FunctionHandle functionHandle = functionResolution.subscriptFunction(baseType, indexType);
        ConstantExpression index = new ConstantExpression(base.getSourceLocation(), Slices.utf8Slice(((Subfield.StringSubscript) pathElement).getIndex()), indexType);
        return new CallExpression(base.getSourceLocation(), SUBSCRIPT.name(), functionHandle, types.get(types.size() - 1), ImmutableList.of(base, index));
    }
    if (pathElement instanceof Subfield.NestedField) {
        Subfield.NestedField nestedField = (Subfield.NestedField) pathElement;
        return new SpecialFormExpression(base.getSourceLocation(), DEREFERENCE, types.get(types.size() - 1), base, new ConstantExpression(base.getSourceLocation(), getFieldIndex((RowType) baseType, nestedField.getName()), INTEGER));
    }
    verify(false, "Unexpected path element: " + pathElement);
    return null;
}
Also used : ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) RowExpression(com.facebook.presto.spi.relation.RowExpression) MapType(com.facebook.presto.common.type.MapType) MapType(com.facebook.presto.common.type.MapType) Varchars.isVarcharType(com.facebook.presto.common.type.Varchars.isVarcharType) ArrayType(com.facebook.presto.common.type.ArrayType) Type(com.facebook.presto.common.type.Type) RowType(com.facebook.presto.common.type.RowType) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) Subfield(com.facebook.presto.common.Subfield)

Example 2 with SpecialFormExpression

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

the class OrCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generator, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
    Preconditions.checkArgument(arguments.size() == 2);
    // We flatten the AND here.
    Deque<RowExpression> stack = new ArrayDeque<>();
    stack.push(arguments.get(1));
    stack.push(arguments.get(0));
    ImmutableList.Builder<RowExpression> flattenedArgs = ImmutableList.builder();
    do {
        RowExpression operand = stack.pop();
        if (operand instanceof SpecialFormExpression && ((SpecialFormExpression) operand).getForm() == SpecialFormExpression.Form.OR) {
            stack.push(((SpecialFormExpression) operand).getArguments().get(1));
            stack.push(((SpecialFormExpression) operand).getArguments().get(0));
        } else {
            flattenedArgs.add(operand);
        }
    } while (!stack.isEmpty());
    BytecodeBlock block = new BytecodeBlock().comment("OR").setDescription("OR");
    LabelNode trueLabel = new LabelNode("true");
    LabelNode endLabel = new LabelNode("end");
    Variable wasNull = generator.wasNull();
    Variable hasNulls = generator.getScope().createTempVariable(boolean.class);
    block.initializeVariable(hasNulls);
    for (RowExpression expression : flattenedArgs.build()) {
        block.comment("do { eval arg; if (wasNull) { hasNull = true; wasNull = false; } else if (true) goto ret_true; }").append(generator.generate(expression, Optional.empty()));
        IfStatement ifOperandIsNull = new IfStatement("if left wasNulll...").condition(wasNull);
        ifOperandIsNull.ifTrue().comment("clear the null flag and remember there was a null").putVariable(hasNulls, true).putVariable(wasNull, false).pop(boolean.class);
        ifOperandIsNull.ifFalse().ifTrueGoto(trueLabel);
        block.append(ifOperandIsNull);
    }
    // We evaluated all operands. So check if any of them was null
    IfStatement ifHasNulls = new IfStatement("hasNulls is true");
    ifHasNulls.condition().append(hasNulls);
    ifHasNulls.ifTrue().comment("at least one of the arguments is null and none of them is true. So set wasNull to true").putVariable(wasNull, true).push(false);
    ifHasNulls.ifFalse().push(false);
    block.append(ifHasNulls).gotoLabel(endLabel);
    block.visitLabel(trueLabel).comment("at least one of the args is true, clear wasNull and return true").push(true).gotoLabel(endLabel);
    block.visitLabel(endLabel);
    outputBlockVariable.ifPresent(output -> block.append(generateWrite(generator, returnType, output)));
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) ImmutableList(com.google.common.collect.ImmutableList) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) ArrayDeque(java.util.ArrayDeque)

Example 3 with SpecialFormExpression

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

the class RewriteAggregationIfToFilter method shouldRewriteAggregation.

private boolean shouldRewriteAggregation(Aggregation aggregation, ProjectNode sourceProject) {
    if (functionAndTypeManager.getFunctionMetadata(aggregation.getFunctionHandle()).isCalledOnNullInput()) {
        // This rewrite will filter out the null values. It could change the behavior if the aggregation is also applied on NULLs.
        return false;
    }
    if (!(aggregation.getArguments().size() == 1 && aggregation.getArguments().get(0) instanceof VariableReferenceExpression)) {
        // Currently we only handle aggregation with a single VariableReferenceExpression. The detailed expressions are in a project node below this aggregation.
        return false;
    }
    if (aggregation.getFilter().isPresent() || aggregation.getMask().isPresent()) {
        // Do not rewrite the aggregation if it already has a filter or mask.
        return false;
    }
    RowExpression sourceExpression = sourceProject.getAssignments().get((VariableReferenceExpression) aggregation.getArguments().get(0));
    if (sourceExpression instanceof CallExpression) {
        CallExpression callExpression = (CallExpression) sourceExpression;
        if (callExpression.getArguments().size() == 1 && standardFunctionResolution.isCastFunction(callExpression.getFunctionHandle())) {
            // If the expression is CAST(), check the expression inside.
            sourceExpression = callExpression.getArguments().get(0);
        }
    }
    if (!(sourceExpression instanceof SpecialFormExpression) || !rowExpressionDeterminismEvaluator.isDeterministic(sourceExpression)) {
        return false;
    }
    SpecialFormExpression expression = (SpecialFormExpression) sourceExpression;
    // Only rewrite the aggregation if the else branch is not present or the else result is NULL.
    return expression.getForm() == IF && Expressions.isNull(expression.getArguments().get(2));
}
Also used : VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) RowExpression(com.facebook.presto.spi.relation.RowExpression) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression)

Example 4 with SpecialFormExpression

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

the class TestRowExpressionFormatter method testComplex.

@Test
public void testComplex() {
    RowExpression complexExpression;
    RowExpression expression = createCallExpression(ADD);
    complexExpression = call(SUBTRACT.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(SUBTRACT, fromTypes(BIGINT, BIGINT)), BIGINT, C_BIGINT, expression);
    assertEquals(format(complexExpression), "(c_bigint) - ((c_bigint) + (BIGINT'5'))");
    RowExpression expression1 = createCallExpression(ADD);
    RowExpression expression2 = call(MULTIPLY.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(MULTIPLY, fromTypes(BIGINT, BIGINT)), BIGINT, expression1, C_BIGINT);
    RowExpression expression3 = createCallExpression(GREATER_THAN);
    complexExpression = new SpecialFormExpression(OR, BOOLEAN, expression2, expression3);
    assertEquals(format(complexExpression), "(((c_bigint) + (BIGINT'5')) * (c_bigint)) OR ((c_bigint) > (BIGINT'5'))");
    ArrayType arrayType = (ArrayType) C_BIGINT_ARRAY.getType();
    Type elementType = arrayType.getElementType();
    expression1 = call(SUBSCRIPT.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(SUBSCRIPT, fromTypes(arrayType, elementType)), elementType, ImmutableList.of(C_BIGINT_ARRAY, constant(5L, INTEGER)));
    expression2 = call(NEGATION.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(NEGATION, fromTypes(expression1.getType())), expression1.getType(), expression1);
    expression3 = call(ADD.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(ADD, fromTypes(expression2.getType(), BIGINT)), BIGINT, expression2, constant(5L, BIGINT));
    assertEquals(format(expression3), "(-(c_bigint_array[INTEGER'5'])) + (BIGINT'5')");
}
Also used : ArrayType(com.facebook.presto.common.type.ArrayType) CharType.createCharType(com.facebook.presto.common.type.CharType.createCharType) DecimalType(com.facebook.presto.common.type.DecimalType) CastType(com.facebook.presto.metadata.CastType) ArrayType(com.facebook.presto.common.type.ArrayType) Type(com.facebook.presto.common.type.Type) OperatorType(com.facebook.presto.common.function.OperatorType) RowExpression(com.facebook.presto.spi.relation.RowExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) Test(org.testng.annotations.Test)

Example 5 with SpecialFormExpression

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

the class TestPageFunctionCompiler method testCommonSubExpressionInFilter.

@Test
public void testCommonSubExpressionInFilter() {
    PageFunctionCompiler functionCompiler = new PageFunctionCompiler(createTestMetadataManager(), 0);
    Supplier<PageFilter> pageFilter = functionCompiler.compileFilter(SESSION.getSqlFunctionProperties(), new SpecialFormExpression(AND, BIGINT, ADD_X_Y_GREATER_THAN_2, ADD_X_Y_LESS_THAN_10), true, Optional.empty());
    Page input = createLongBlockPage(2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    SelectedPositions positions = filter(pageFilter.get(), input);
    assertEquals(positions.size(), 3);
    assertEquals(positions.getPositions(), new int[] { 2, 3, 4 });
}
Also used : SelectedPositions(com.facebook.presto.operator.project.SelectedPositions) PageFilter(com.facebook.presto.operator.project.PageFilter) Page(com.facebook.presto.common.Page) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) Test(org.testng.annotations.Test)

Aggregations

SpecialFormExpression (com.facebook.presto.spi.relation.SpecialFormExpression)23 RowExpression (com.facebook.presto.spi.relation.RowExpression)19 ConstantExpression (com.facebook.presto.spi.relation.ConstantExpression)9 VariableReferenceExpression (com.facebook.presto.spi.relation.VariableReferenceExpression)9 CallExpression (com.facebook.presto.spi.relation.CallExpression)8 ImmutableList (com.google.common.collect.ImmutableList)7 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)6 Test (org.testng.annotations.Test)6 Variable (com.facebook.presto.bytecode.Variable)5 Type (com.facebook.presto.common.type.Type)5 IfStatement (com.facebook.presto.bytecode.control.IfStatement)4 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)4 Page (com.facebook.presto.common.Page)4 RowType (com.facebook.presto.common.type.RowType)4 Scope (com.facebook.presto.bytecode.Scope)3 Subfield (com.facebook.presto.common.Subfield)3 LambdaDefinitionExpression (com.facebook.presto.spi.relation.LambdaDefinitionExpression)3 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)3 ArrayDeque (java.util.ArrayDeque)3 ArrayList (java.util.ArrayList)3