Search in sources :

Example 16 with SpecialFormExpression

use of com.facebook.presto.spi.relation.SpecialFormExpression in project urban-eureka by errir503.

the class ParquetDereferencePushDown method createNestedColumn.

private Subfield createNestedColumn(Map<String, ColumnHandle> baseColumnHandles, RowExpression rowExpression, ExpressionOptimizer expressionOptimizer, ConnectorSession session) {
    if (!(rowExpression instanceof SpecialFormExpression) || ((SpecialFormExpression) rowExpression).getForm() != DEREFERENCE) {
        throw new IllegalArgumentException("expecting SpecialFormExpression(DEREFERENCE), but got: " + rowExpression);
    }
    RowExpression currentRowExpression = rowExpression;
    List<Subfield.PathElement> elements = new ArrayList<>();
    while (true) {
        if (currentRowExpression instanceof VariableReferenceExpression) {
            Collections.reverse(elements);
            String name = ((VariableReferenceExpression) currentRowExpression).getName();
            ColumnHandle handle = baseColumnHandles.get(name);
            checkArgument(handle != null, "Missing Column handle: " + name);
            String originalColumnName = getColumnName(handle);
            return new Subfield(originalColumnName, unmodifiableList(elements));
        }
        if (currentRowExpression instanceof SpecialFormExpression && ((SpecialFormExpression) currentRowExpression).getForm() == DEREFERENCE) {
            SpecialFormExpression dereferenceExpression = (SpecialFormExpression) currentRowExpression;
            RowExpression base = dereferenceExpression.getArguments().get(0);
            RowType baseType = (RowType) base.getType();
            RowExpression indexExpression = expressionOptimizer.optimize(dereferenceExpression.getArguments().get(1), ExpressionOptimizer.Level.OPTIMIZED, session);
            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()));
                        currentRowExpression = base;
                        continue;
                    }
                }
            }
        }
        break;
    }
    throw new IllegalArgumentException("expecting SpecialFormExpression(DEREFERENCE) with constants for indices, but got: " + currentRowExpression);
}
Also used : ColumnHandle(com.facebook.presto.spi.ColumnHandle) 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) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) ParquetTypeUtils.pushdownColumnNameForSubfield(com.facebook.presto.parquet.ParquetTypeUtils.pushdownColumnNameForSubfield) Subfield(com.facebook.presto.common.Subfield)

Example 17 with SpecialFormExpression

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

the class LogicalRowExpressions method extractPredicates.

public static List<RowExpression> extractPredicates(Form form, RowExpression expression) {
    if (expression instanceof SpecialFormExpression && ((SpecialFormExpression) expression).getForm() == form) {
        SpecialFormExpression specialFormExpression = (SpecialFormExpression) expression;
        if (specialFormExpression.getArguments().size() == 2) {
            List<RowExpression> predicates = new ArrayList<>();
            predicates.addAll(extractPredicates(form, specialFormExpression.getArguments().get(0)));
            predicates.addAll(extractPredicates(form, specialFormExpression.getArguments().get(1)));
            return unmodifiableList(predicates);
        }
        if (specialFormExpression.getArguments().size() == 1 && form == IS_NULL) {
            return singletonList(expression);
        }
        throw new IllegalStateException("Unexpected operands:" + expression + " " + form);
    }
    return singletonList(expression);
}
Also used : ArrayList(java.util.ArrayList) RowExpression(com.facebook.presto.spi.relation.RowExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression)

Example 18 with SpecialFormExpression

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

the class LogicalRowExpressions method binaryExpression.

public static RowExpression binaryExpression(Form form, Collection<? extends RowExpression> expressions) {
    requireNonNull(form, "operator is null");
    requireNonNull(expressions, "expressions is null");
    if (expressions.isEmpty()) {
        switch(form) {
            case AND:
                return TRUE_CONSTANT;
            case OR:
                return FALSE_CONSTANT;
            default:
                throw new IllegalArgumentException("Unsupported binary expression operator");
        }
    }
    // Build balanced tree for efficient recursive processing that
    // preserves the evaluation order of the input expressions.
    // 
    // The tree is built bottom up by combining pairs of elements into
    // binary AND expressions.
    // 
    // Example:
    // 
    // Initial state:
    // a b c d e
    // 
    // First iteration:
    // 
    // /\    /\   e
    // a  b  c  d
    // 
    // Second iteration:
    // 
    // / \    e
    // /\   /\
    // a  b c  d
    // 
    // 
    // Last iteration:
    // 
    // / \
    // / \  e
    // /\   /\
    // a  b c  d
    Queue<RowExpression> queue = new ArrayDeque<>(expressions);
    while (queue.size() > 1) {
        Queue<RowExpression> buffer = new ArrayDeque<>();
        // combine pairs of elements
        while (queue.size() >= 2) {
            List<RowExpression> arguments = asList(queue.remove(), queue.remove());
            buffer.add(new SpecialFormExpression(form, BOOLEAN, arguments));
        }
        // if there's and odd number of elements, just append the last one
        if (!queue.isEmpty()) {
            buffer.add(queue.remove());
        }
        // continue processing the pairs that were just built
        queue = buffer;
    }
    return queue.remove();
}
Also used : RowExpression(com.facebook.presto.spi.relation.RowExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) ArrayDeque(java.util.ArrayDeque)

Example 19 with SpecialFormExpression

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

the class RewriteAggregationIfToFilter method apply.

@Override
public Result apply(AggregationNode aggregationNode, Captures captures, Context context) {
    ProjectNode sourceProject = captures.get(CHILD);
    Set<Aggregation> aggregationsToRewrite = aggregationNode.getAggregations().values().stream().filter(aggregation -> shouldRewriteAggregation(aggregation, sourceProject)).collect(toImmutableSet());
    if (aggregationsToRewrite.isEmpty()) {
        return Result.empty();
    }
    context.getSession().getRuntimeStats().addMetricValue(REWRITE_AGGREGATION_IF_TO_FILTER_APPLIED, 1);
    // Get the corresponding assignments in the input project.
    // The aggregationReferences only has the aggregations to rewrite, thus the sourceAssignments only has IF/CAST(IF) expressions with NULL false results.
    // Multiple aggregations may reference the same input. We use a map to dedup them based on the VariableReferenceExpression, so that we only do the rewrite once per input
    // IF expression.
    // The order of sourceAssignments determines the order of generating the new variables for the IF conditions and results. We use a sorted map to get a deterministic
    // order based on the name of the VariableReferenceExpressions.
    Map<VariableReferenceExpression, RowExpression> sourceAssignments = aggregationsToRewrite.stream().map(aggregation -> (VariableReferenceExpression) aggregation.getArguments().get(0)).collect(toImmutableSortedMap(VariableReferenceExpression::compareTo, identity(), variable -> sourceProject.getAssignments().get(variable), (left, right) -> left));
    Assignments.Builder newAssignments = Assignments.builder();
    newAssignments.putAll(sourceProject.getAssignments());
    // Map from the aggregation reference to the IF condition reference which will be put in the mask.
    Map<VariableReferenceExpression, VariableReferenceExpression> aggregationReferenceToConditionReference = new HashMap<>();
    // Map from the aggregation reference to the IF result reference. This only contains the aggregates where the IF can be safely unwrapped.
    // E.g., SUM(IF(CARDINALITY(array) > 0, array[1])) will not be included in this map as array[1] can return errors if we unwrap the IF.
    Map<VariableReferenceExpression, VariableReferenceExpression> aggregationReferenceToIfResultReference = new HashMap<>();
    AggregationIfToFilterRewriteStrategy rewriteStrategy = getAggregationIfToFilterRewriteStrategy(context.getSession());
    for (Map.Entry<VariableReferenceExpression, RowExpression> entry : sourceAssignments.entrySet()) {
        VariableReferenceExpression outputVariable = entry.getKey();
        RowExpression rowExpression = entry.getValue();
        SpecialFormExpression ifExpression = (SpecialFormExpression) ((rowExpression instanceof CallExpression) ? ((CallExpression) rowExpression).getArguments().get(0) : rowExpression);
        RowExpression condition = ifExpression.getArguments().get(0);
        VariableReferenceExpression conditionReference = context.getVariableAllocator().newVariable(condition);
        newAssignments.put(conditionReference, condition);
        aggregationReferenceToConditionReference.put(outputVariable, conditionReference);
        if (canUnwrapIf(ifExpression, rewriteStrategy)) {
            RowExpression trueResult = ifExpression.getArguments().get(1);
            if (rowExpression instanceof CallExpression) {
                // Wrap the result with CAST().
                trueResult = new CallExpression(((CallExpression) rowExpression).getDisplayName(), ((CallExpression) rowExpression).getFunctionHandle(), rowExpression.getType(), ImmutableList.of(trueResult));
            }
            VariableReferenceExpression ifResultReference = context.getVariableAllocator().newVariable(trueResult);
            newAssignments.put(ifResultReference, trueResult);
            aggregationReferenceToIfResultReference.put(outputVariable, ifResultReference);
        }
    }
    // Build new aggregations.
    ImmutableMap.Builder<VariableReferenceExpression, Aggregation> aggregations = ImmutableMap.builder();
    // Stores the masks used to build the filter predicates. Use set to dedup the predicates.
    ImmutableSortedSet.Builder<VariableReferenceExpression> masks = ImmutableSortedSet.naturalOrder();
    for (Map.Entry<VariableReferenceExpression, Aggregation> entry : aggregationNode.getAggregations().entrySet()) {
        VariableReferenceExpression output = entry.getKey();
        Aggregation aggregation = entry.getValue();
        if (!aggregationsToRewrite.contains(aggregation)) {
            aggregations.put(output, aggregation);
            continue;
        }
        VariableReferenceExpression aggregationReference = (VariableReferenceExpression) aggregation.getArguments().get(0);
        CallExpression callExpression = aggregation.getCall();
        VariableReferenceExpression ifResultReference = aggregationReferenceToIfResultReference.get(aggregationReference);
        if (ifResultReference != null) {
            callExpression = new CallExpression(callExpression.getSourceLocation(), callExpression.getDisplayName(), callExpression.getFunctionHandle(), callExpression.getType(), ImmutableList.of(ifResultReference));
        }
        VariableReferenceExpression mask = aggregationReferenceToConditionReference.get(aggregationReference);
        aggregations.put(output, new Aggregation(callExpression, Optional.empty(), aggregation.getOrderBy(), aggregation.isDistinct(), Optional.of(aggregationReferenceToConditionReference.get(aggregationReference))));
        masks.add(mask);
    }
    RowExpression predicate = TRUE_CONSTANT;
    if (!aggregationNode.hasNonEmptyGroupingSet() && aggregationsToRewrite.size() == aggregationNode.getAggregations().size()) {
        // All aggregations are rewritten by this rule. We can add a filter with all the masks to make the query more efficient.
        predicate = or(masks.build());
    }
    return Result.ofPlanNode(new AggregationNode(aggregationNode.getSourceLocation(), context.getIdAllocator().getNextId(), new FilterNode(aggregationNode.getSourceLocation(), context.getIdAllocator().getNextId(), new ProjectNode(context.getIdAllocator().getNextId(), sourceProject.getSource(), newAssignments.build()), predicate), aggregations.build(), aggregationNode.getGroupingSets(), aggregationNode.getPreGroupedVariables(), aggregationNode.getStep(), aggregationNode.getHashVariable(), aggregationNode.getGroupIdVariable()));
}
Also used : FunctionAndTypeManager(com.facebook.presto.metadata.FunctionAndTypeManager) AggregationNode(com.facebook.presto.spi.plan.AggregationNode) Captures(com.facebook.presto.matching.Captures) Assignments(com.facebook.presto.spi.plan.Assignments) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ImmutableSortedMap.toImmutableSortedMap(com.google.common.collect.ImmutableSortedMap.toImmutableSortedMap) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) HashMap(java.util.HashMap) RowExpressionDeterminismEvaluator(com.facebook.presto.sql.relational.RowExpressionDeterminismEvaluator) SystemSessionProperties.getAggregationIfToFilterRewriteStrategy(com.facebook.presto.SystemSessionProperties.getAggregationIfToFilterRewriteStrategy) StandardFunctionResolution(com.facebook.presto.spi.function.StandardFunctionResolution) Pattern(com.facebook.presto.matching.Pattern) FilterNode(com.facebook.presto.spi.plan.FilterNode) Capture(com.facebook.presto.matching.Capture) ImmutableList(com.google.common.collect.ImmutableList) UNWRAP_IF(com.facebook.presto.sql.analyzer.FeaturesConfig.AggregationIfToFilterRewriteStrategy.UNWRAP_IF) IF(com.facebook.presto.spi.relation.SpecialFormExpression.Form.IF) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) Expressions(com.facebook.presto.sql.relational.Expressions) FunctionResolution(com.facebook.presto.sql.relational.FunctionResolution) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) VariablesExtractor(com.facebook.presto.sql.planner.VariablesExtractor) RowExpression(com.facebook.presto.spi.relation.RowExpression) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) Patterns.aggregation(com.facebook.presto.sql.planner.plan.Patterns.aggregation) ImmutableMap(com.google.common.collect.ImmutableMap) Session(com.facebook.presto.Session) Rule(com.facebook.presto.sql.planner.iterative.Rule) Patterns.project(com.facebook.presto.sql.planner.plan.Patterns.project) Set(java.util.Set) LambdaDefinitionExpression(com.facebook.presto.spi.relation.LambdaDefinitionExpression) OperatorType(com.facebook.presto.common.function.OperatorType) AggregationIfToFilterRewriteStrategy(com.facebook.presto.sql.analyzer.FeaturesConfig.AggregationIfToFilterRewriteStrategy) TRUE_CONSTANT(com.facebook.presto.expressions.LogicalRowExpressions.TRUE_CONSTANT) Patterns.source(com.facebook.presto.sql.planner.plan.Patterns.source) FILTER_WITH_IF(com.facebook.presto.sql.analyzer.FeaturesConfig.AggregationIfToFilterRewriteStrategy.FILTER_WITH_IF) DefaultRowExpressionTraversalVisitor(com.facebook.presto.expressions.DefaultRowExpressionTraversalVisitor) ProjectNode(com.facebook.presto.spi.plan.ProjectNode) LogicalRowExpressions.or(com.facebook.presto.expressions.LogicalRowExpressions.or) Capture.newCapture(com.facebook.presto.matching.Capture.newCapture) Aggregation(com.facebook.presto.spi.plan.AggregationNode.Aggregation) Function.identity(java.util.function.Function.identity) Optional(java.util.Optional) REWRITE_AGGREGATION_IF_TO_FILTER_APPLIED(com.facebook.presto.common.RuntimeMetricName.REWRITE_AGGREGATION_IF_TO_FILTER_APPLIED) SystemSessionProperties.getAggregationIfToFilterRewriteStrategy(com.facebook.presto.SystemSessionProperties.getAggregationIfToFilterRewriteStrategy) AggregationIfToFilterRewriteStrategy(com.facebook.presto.sql.analyzer.FeaturesConfig.AggregationIfToFilterRewriteStrategy) HashMap(java.util.HashMap) FilterNode(com.facebook.presto.spi.plan.FilterNode) Assignments(com.facebook.presto.spi.plan.Assignments) RowExpression(com.facebook.presto.spi.relation.RowExpression) AggregationNode(com.facebook.presto.spi.plan.AggregationNode) ImmutableMap(com.google.common.collect.ImmutableMap) Aggregation(com.facebook.presto.spi.plan.AggregationNode.Aggregation) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) ProjectNode(com.facebook.presto.spi.plan.ProjectNode) ImmutableSortedMap.toImmutableSortedMap(com.google.common.collect.ImmutableSortedMap.toImmutableSortedMap) HashMap(java.util.HashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) CallExpression(com.facebook.presto.spi.relation.CallExpression)

Example 20 with SpecialFormExpression

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

the class CursorProcessorCompiler method fieldReferenceCompiler.

static RowExpressionVisitor<BytecodeNode, Scope> fieldReferenceCompiler(Map<VariableReferenceExpression, CommonSubExpressionFields> variableMap) {
    return new RowExpressionVisitor<BytecodeNode, Scope>() {

        @Override
        public BytecodeNode visitInputReference(InputReferenceExpression node, Scope scope) {
            int field = node.getField();
            Type type = node.getType();
            Variable wasNullVariable = scope.getVariable("wasNull");
            Variable cursorVariable = scope.getVariable("cursor");
            Class<?> javaType = type.getJavaType();
            if (!javaType.isPrimitive() && javaType != Slice.class) {
                javaType = Object.class;
            }
            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).invokeInterface(RecordCursor.class, "get" + Primitives.wrap(javaType).getSimpleName(), javaType, int.class);
            return ifStatement;
        }

        @Override
        public BytecodeNode visitCall(CallExpression call, Scope scope) {
            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) {
            CommonSubExpressionFields fields = variableMap.get(reference);
            return new BytecodeBlock().append(context.getThis().invoke(fields.getMethodName(), fields.getResultType(), context.getVariable("properties"), context.getVariable("cursor"))).append(unboxPrimitiveIfNecessary(context, Primitives.wrap(reference.getType().getJavaType())));
        }

        @Override
        public BytecodeNode visitSpecialForm(SpecialFormExpression specialForm, Scope context) {
            throw new UnsupportedOperationException();
        }
    };
}
Also used : InputReferenceExpression(com.facebook.presto.spi.relation.InputReferenceExpression) Variable(com.facebook.presto.bytecode.Variable) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Type(com.facebook.presto.common.type.Type) CommonSubExpressionFields.initializeCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.initializeCommonSubExpressionFields) CommonSubExpressionFields.declareCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.declareCommonSubExpressionFields) CommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields) Scope(com.facebook.presto.bytecode.Scope) Slice(io.airlift.slice.Slice) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) RowExpressionVisitor(com.facebook.presto.spi.relation.RowExpressionVisitor) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) LambdaDefinitionExpression(com.facebook.presto.spi.relation.LambdaDefinitionExpression)

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