Search in sources :

Example 16 with ValuesNode

use of io.prestosql.spi.plan.ValuesNode in project hetu-core by openlookeng.

the class PruneValuesColumns method pushDownProjectOff.

@Override
protected Optional<PlanNode> pushDownProjectOff(PlanNodeIdAllocator idAllocator, ValuesNode valuesNode, Set<Symbol> referencedOutputs) {
    List<Symbol> newOutputs = filteredCopy(valuesNode.getOutputSymbols(), referencedOutputs::contains);
    // for each output of project, the corresponding column in the values node
    int[] mapping = new int[newOutputs.size()];
    for (int i = 0; i < mapping.length; i++) {
        mapping[i] = valuesNode.getOutputSymbols().indexOf(newOutputs.get(i));
    }
    ImmutableList.Builder<List<RowExpression>> rowsBuilder = ImmutableList.builder();
    for (List<RowExpression> row : valuesNode.getRows()) {
        rowsBuilder.add(Arrays.stream(mapping).mapToObj(row::get).collect(Collectors.toList()));
    }
    return Optional.of(new ValuesNode(valuesNode.getId(), newOutputs, rowsBuilder.build()));
}
Also used : ValuesNode(io.prestosql.spi.plan.ValuesNode) Symbol(io.prestosql.spi.plan.Symbol) ImmutableList(com.google.common.collect.ImmutableList) RowExpression(io.prestosql.spi.relation.RowExpression) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList)

Example 17 with ValuesNode

use of io.prestosql.spi.plan.ValuesNode in project hetu-core by openlookeng.

the class PushPredicateIntoTableScan method pushPredicateIntoTableScan.

/**
 * For RowExpression {@param predicate}
 */
public static Optional<PlanNode> pushPredicateIntoTableScan(TableScanNode node, RowExpression predicate, boolean pruneWithPredicateExpression, Session session, PlanNodeIdAllocator idAllocator, PlanSymbolAllocator planSymbolAllocator, Metadata metadata, RowExpressionDomainTranslator domainTranslator, boolean pushPartitionsOnly) {
    // don't include non-deterministic predicates
    LogicalRowExpressions logicalRowExpressions = new LogicalRowExpressions(new RowExpressionDeterminismEvaluator(metadata), new FunctionResolution(metadata.getFunctionAndTypeManager()), metadata.getFunctionAndTypeManager());
    RowExpression deterministicPredicate = logicalRowExpressions.filterDeterministicConjuncts(predicate);
    RowExpressionDomainTranslator.ExtractionResult<VariableReferenceExpression> decomposedPredicate = domainTranslator.fromPredicate(session.toConnectorSession(), deterministicPredicate);
    TupleDomain<ColumnHandle> newDomain = decomposedPredicate.getTupleDomain().transform(variableName -> node.getAssignments().get(new Symbol(variableName.getName()))).intersect(node.getEnforcedConstraint());
    Map<ColumnHandle, Symbol> assignments = ImmutableBiMap.copyOf(node.getAssignments()).inverse();
    Set<ColumnHandle> allColumnHandles = new HashSet<>();
    assignments.keySet().stream().forEach(allColumnHandles::add);
    Constraint constraint;
    List<Constraint> disjunctConstraints = ImmutableList.of();
    if (!pushPartitionsOnly) {
        List<RowExpression> orSet = LogicalRowExpressions.extractDisjuncts(decomposedPredicate.getRemainingExpression());
        List<RowExpressionDomainTranslator.ExtractionResult<VariableReferenceExpression>> disjunctPredicates = orSet.stream().map(e -> domainTranslator.fromPredicate(session.toConnectorSession(), e)).collect(Collectors.toList());
        /* Check if any Branch yeild all records; then no need to process OR branches */
        if (!disjunctPredicates.stream().anyMatch(e -> e.getTupleDomain().isAll())) {
            List<TupleDomain<ColumnHandle>> orDomains = disjunctPredicates.stream().map(er -> er.getTupleDomain().transform(variableName -> node.getAssignments().get(new Symbol(variableName.getName())))).collect(Collectors.toList());
            disjunctConstraints = orDomains.stream().filter(d -> !d.isAll() && !d.isNone()).map(d -> new Constraint(d)).collect(Collectors.toList());
        }
    }
    if (pruneWithPredicateExpression) {
        LayoutConstraintEvaluatorForRowExpression evaluator = new LayoutConstraintEvaluatorForRowExpression(metadata, session, node.getAssignments(), logicalRowExpressions.combineConjuncts(deterministicPredicate, // which would be expensive to evaluate in the call to isCandidate below.
        domainTranslator.toPredicate(newDomain.simplify().transform(column -> {
            if (assignments.size() == 0 || assignments.getOrDefault(column, null) == null) {
                return null;
            } else {
                return new VariableReferenceExpression(assignments.getOrDefault(column, null).getName(), planSymbolAllocator.getSymbols().get(assignments.getOrDefault(column, null)));
            }
        }))));
        constraint = new Constraint(newDomain, evaluator::isCandidate);
    } else {
        // Currently, invoking the expression interpreter is very expensive.
        // TODO invoke the interpreter unconditionally when the interpreter becomes cheap enough.
        constraint = new Constraint(newDomain);
    }
    TableHandle newTable;
    TupleDomain<ColumnHandle> remainingFilter;
    if (!metadata.usesLegacyTableLayouts(session, node.getTable())) {
        if (newDomain.isNone()) {
            // to turn the subtree into a Values node
            return Optional.of(new ValuesNode(idAllocator.getNextId(), node.getOutputSymbols(), ImmutableList.of()));
        }
        Optional<ConstraintApplicationResult<TableHandle>> result = metadata.applyFilter(session, node.getTable(), constraint, disjunctConstraints, allColumnHandles, pushPartitionsOnly);
        if (!result.isPresent()) {
            return Optional.empty();
        }
        newTable = result.get().getHandle();
        if (metadata.getTableProperties(session, newTable).getPredicate().isNone()) {
            return Optional.of(new ValuesNode(idAllocator.getNextId(), node.getOutputSymbols(), ImmutableList.of()));
        }
        remainingFilter = result.get().getRemainingFilter();
    } else {
        Optional<TableLayoutResult> layout = metadata.getLayout(session, node.getTable(), constraint, Optional.of(node.getOutputSymbols().stream().map(node.getAssignments()::get).collect(toImmutableSet())));
        if (!layout.isPresent() || layout.get().getTableProperties().getPredicate().isNone()) {
            return Optional.of(new ValuesNode(idAllocator.getNextId(), node.getOutputSymbols(), ImmutableList.of()));
        }
        newTable = layout.get().getNewTableHandle();
        remainingFilter = layout.get().getUnenforcedConstraint();
    }
    TableScanNode tableScan = new TableScanNode(node.getId(), newTable, node.getOutputSymbols(), node.getAssignments(), computeEnforced(newDomain, remainingFilter), Optional.of(deterministicPredicate), node.getStrategy(), node.getReuseTableScanMappingId(), 0, node.isForDelete());
    // The order of the arguments to combineConjuncts matters:
    // * Unenforced constraints go first because they can only be simple column references,
    // which are not prone to logic errors such as out-of-bound access, div-by-zero, etc.
    // * Conjuncts in non-deterministic expressions and non-TupleDomain-expressible expressions should
    // retain their original (maybe intermixed) order from the input predicate. However, this is not implemented yet.
    // * Short of implementing the previous bullet point, the current order of non-deterministic expressions
    // and non-TupleDomain-expressible expressions should be retained. Changing the order can lead
    // to failures of previously successful queries.
    RowExpression resultingPredicate;
    if (remainingFilter.isAll() && newTable.getConnectorHandle().hasDisjunctFiltersPushdown()) {
        resultingPredicate = logicalRowExpressions.combineConjuncts(domainTranslator.toPredicate(remainingFilter.transform(assignments::get), planSymbolAllocator.getSymbols()), logicalRowExpressions.filterNonDeterministicConjuncts(predicate));
    } else {
        resultingPredicate = logicalRowExpressions.combineConjuncts(domainTranslator.toPredicate(remainingFilter.transform(assignments::get), planSymbolAllocator.getSymbols()), logicalRowExpressions.filterNonDeterministicConjuncts(predicate), decomposedPredicate.getRemainingExpression());
    }
    if (!TRUE_CONSTANT.equals(resultingPredicate)) {
        return Optional.of(new FilterNode(idAllocator.getNextId(), tableScan, resultingPredicate));
    }
    return Optional.of(tableScan);
}
Also used : ConstantExpression(io.prestosql.spi.relation.ConstantExpression) LogicalRowExpressions(io.prestosql.expressions.LogicalRowExpressions) TryFunction(io.prestosql.operator.scalar.TryFunction) NullableValue(io.prestosql.spi.predicate.NullableValue) TypeAnalyzer(io.prestosql.sql.planner.TypeAnalyzer) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) Capture.newCapture(io.prestosql.matching.Capture.newCapture) FilterNode(io.prestosql.spi.plan.FilterNode) Map(java.util.Map) Constraint(io.prestosql.spi.connector.Constraint) ConstraintApplicationResult(io.prestosql.spi.connector.ConstraintApplicationResult) RowExpressionDeterminismEvaluator(io.prestosql.sql.relational.RowExpressionDeterminismEvaluator) SymbolsExtractor(io.prestosql.sql.planner.SymbolsExtractor) ImmutableMap(com.google.common.collect.ImmutableMap) TableScanNode(io.prestosql.spi.plan.TableScanNode) Set(java.util.Set) PlanNode(io.prestosql.spi.plan.PlanNode) RowExpressionDomainTranslator(io.prestosql.sql.relational.RowExpressionDomainTranslator) Collectors(java.util.stream.Collectors) Metadata(io.prestosql.metadata.Metadata) PlanSymbolAllocator(io.prestosql.sql.planner.PlanSymbolAllocator) Objects(java.util.Objects) Captures(io.prestosql.matching.Captures) RowExpressionInterpreter(io.prestosql.sql.planner.RowExpressionInterpreter) List(java.util.List) FunctionResolution(io.prestosql.sql.relational.FunctionResolution) TableLayoutResult(io.prestosql.metadata.TableLayoutResult) Capture(io.prestosql.matching.Capture) Optional(java.util.Optional) TRUE_CONSTANT(io.prestosql.expressions.LogicalRowExpressions.TRUE_CONSTANT) Patterns.source(io.prestosql.sql.planner.plan.Patterns.source) Logger(io.airlift.log.Logger) Pattern(io.prestosql.matching.Pattern) TableHandle(io.prestosql.spi.metadata.TableHandle) Function(java.util.function.Function) TableLayoutResult.computeEnforced(io.prestosql.metadata.TableLayoutResult.computeEnforced) OPTIMIZED(io.prestosql.sql.planner.RowExpressionInterpreter.Level.OPTIMIZED) ImmutableBiMap(com.google.common.collect.ImmutableBiMap) HashSet(java.util.HashSet) ImmutableList(com.google.common.collect.ImmutableList) Objects.requireNonNull(java.util.Objects.requireNonNull) Session(io.prestosql.Session) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) Symbol(io.prestosql.spi.plan.Symbol) Rule(io.prestosql.sql.planner.iterative.Rule) Patterns.filter(io.prestosql.sql.planner.plan.Patterns.filter) TupleDomain(io.prestosql.spi.predicate.TupleDomain) VariableReferenceExpression(io.prestosql.spi.relation.VariableReferenceExpression) ValuesNode(io.prestosql.spi.plan.ValuesNode) VariableResolver(io.prestosql.sql.planner.VariableResolver) ColumnHandle(io.prestosql.spi.connector.ColumnHandle) Sets.intersection(com.google.common.collect.Sets.intersection) PlanNodeIdAllocator(io.prestosql.spi.plan.PlanNodeIdAllocator) RowExpression(io.prestosql.spi.relation.RowExpression) Patterns.tableScan(io.prestosql.sql.planner.plan.Patterns.tableScan) ValuesNode(io.prestosql.spi.plan.ValuesNode) Constraint(io.prestosql.spi.connector.Constraint) Symbol(io.prestosql.spi.plan.Symbol) FilterNode(io.prestosql.spi.plan.FilterNode) TableLayoutResult(io.prestosql.metadata.TableLayoutResult) FunctionResolution(io.prestosql.sql.relational.FunctionResolution) ConstraintApplicationResult(io.prestosql.spi.connector.ConstraintApplicationResult) HashSet(java.util.HashSet) RowExpressionDeterminismEvaluator(io.prestosql.sql.relational.RowExpressionDeterminismEvaluator) ColumnHandle(io.prestosql.spi.connector.ColumnHandle) LogicalRowExpressions(io.prestosql.expressions.LogicalRowExpressions) RowExpressionDomainTranslator(io.prestosql.sql.relational.RowExpressionDomainTranslator) RowExpression(io.prestosql.spi.relation.RowExpression) TupleDomain(io.prestosql.spi.predicate.TupleDomain) TableScanNode(io.prestosql.spi.plan.TableScanNode) VariableReferenceExpression(io.prestosql.spi.relation.VariableReferenceExpression) TableHandle(io.prestosql.spi.metadata.TableHandle)

Example 18 with ValuesNode

use of io.prestosql.spi.plan.ValuesNode in project hetu-core by openlookeng.

the class PushAggregationThroughOuterJoin method createAggregationOverNull.

private Optional<MappedAggregationInfo> createAggregationOverNull(AggregationNode referenceAggregation, PlanSymbolAllocator planSymbolAllocator, PlanNodeIdAllocator idAllocator, Lookup lookup) {
    // Create a values node that consists of a single row of nulls.
    // Map the output symbols from the referenceAggregation's source
    // to symbol references for the new values node.
    ImmutableList.Builder<Symbol> nullSymbols = ImmutableList.builder();
    ImmutableList.Builder<RowExpression> nullLiterals = ImmutableList.builder();
    ImmutableMap.Builder<VariableReferenceExpression, VariableReferenceExpression> sourcesSymbolMappingBuilder = ImmutableMap.builder();
    for (Symbol sourceSymbol : referenceAggregation.getSource().getOutputSymbols()) {
        RowExpression nullLiteral = new ConstantExpression(null, planSymbolAllocator.getTypes().get(sourceSymbol));
        nullLiterals.add(nullLiteral);
        Symbol nullSymbol = planSymbolAllocator.newSymbol(nullLiteral);
        nullSymbols.add(nullSymbol);
        sourcesSymbolMappingBuilder.put(toVariableReference(sourceSymbol, planSymbolAllocator.getTypes().get(sourceSymbol)), toVariableReference(nullSymbol, nullLiteral.getType()));
    }
    ValuesNode nullRow = new ValuesNode(idAllocator.getNextId(), nullSymbols.build(), ImmutableList.of(nullLiterals.build()));
    Map<VariableReferenceExpression, VariableReferenceExpression> sourcesSymbolMapping = sourcesSymbolMappingBuilder.build();
    // For each aggregation function in the reference node, create a corresponding aggregation function
    // that points to the nullRow. Map the symbols from the aggregations in referenceAggregation to the
    // symbols in these new aggregations.
    ImmutableMap.Builder<Symbol, Symbol> aggregationsSymbolMappingBuilder = ImmutableMap.builder();
    ImmutableMap.Builder<Symbol, AggregationNode.Aggregation> aggregationsOverNullBuilder = ImmutableMap.builder();
    for (Map.Entry<Symbol, AggregationNode.Aggregation> entry : referenceAggregation.getAggregations().entrySet()) {
        Symbol aggregationSymbol = entry.getKey();
        AggregationNode.Aggregation aggregation = entry.getValue();
        if (!isUsingVariables(aggregation, sourcesSymbolMapping.keySet())) {
            return Optional.empty();
        }
        Aggregation overNullAggregation = new Aggregation(new CallExpression(aggregation.getFunctionCall().getDisplayName(), aggregation.getFunctionCall().getFunctionHandle(), aggregation.getFunctionCall().getType(), aggregation.getArguments().stream().map(argument -> inlineVariables(sourcesSymbolMapping, argument)).collect(toImmutableList()), Optional.empty()), aggregation.getArguments().stream().map(argument -> inlineVariables(sourcesSymbolMapping, argument)).collect(toImmutableList()), aggregation.isDistinct(), aggregation.getFilter(), aggregation.getOrderingScheme(), aggregation.getMask());
        Symbol overNullSymbol = planSymbolAllocator.newSymbol(overNullAggregation.getFunctionCall().getDisplayName(), planSymbolAllocator.getTypes().get(aggregationSymbol));
        aggregationsOverNullBuilder.put(overNullSymbol, overNullAggregation);
        aggregationsSymbolMappingBuilder.put(aggregationSymbol, overNullSymbol);
    }
    Map<Symbol, Symbol> aggregationsSymbolMapping = aggregationsSymbolMappingBuilder.build();
    // create an aggregation node whose source is the null row.
    AggregationNode aggregationOverNullRow = new AggregationNode(idAllocator.getNextId(), nullRow, aggregationsOverNullBuilder.build(), globalAggregation(), ImmutableList.of(), AggregationNode.Step.SINGLE, Optional.empty(), Optional.empty(), AggregationNode.AggregationType.HASH, Optional.empty());
    return Optional.of(new MappedAggregationInfo(aggregationOverNullRow, aggregationsSymbolMapping));
}
Also used : Patterns.source(io.prestosql.sql.planner.plan.Patterns.source) ConstantExpression(io.prestosql.spi.relation.ConstantExpression) Lookup(io.prestosql.sql.planner.iterative.Lookup) Patterns.aggregation(io.prestosql.sql.planner.plan.Patterns.aggregation) Patterns.join(io.prestosql.sql.planner.plan.Patterns.join) Pattern(io.prestosql.matching.Pattern) SystemSessionProperties.shouldPushAggregationThroughJoin(io.prestosql.SystemSessionProperties.shouldPushAggregationThroughJoin) AggregationNode(io.prestosql.spi.plan.AggregationNode) HashSet(java.util.HashSet) CallExpression(io.prestosql.spi.relation.CallExpression) Capture.newCapture(io.prestosql.matching.Capture.newCapture) ImmutableList(com.google.common.collect.ImmutableList) RowExpressionVariableInliner.inlineVariables(io.prestosql.sql.planner.RowExpressionVariableInliner.inlineVariables) Map(java.util.Map) Session(io.prestosql.Session) SpecialForm(io.prestosql.spi.relation.SpecialForm) AggregationNode.globalAggregation(io.prestosql.spi.plan.AggregationNode.globalAggregation) JoinNode(io.prestosql.spi.plan.JoinNode) AggregationNode.singleGroupingSet(io.prestosql.spi.plan.AggregationNode.singleGroupingSet) Symbol(io.prestosql.spi.plan.Symbol) ImmutableMap(com.google.common.collect.ImmutableMap) Assignments(io.prestosql.spi.plan.Assignments) Rule(io.prestosql.sql.planner.iterative.Rule) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Set(java.util.Set) PlanNode(io.prestosql.spi.plan.PlanNode) VariableReferenceExpression(io.prestosql.spi.relation.VariableReferenceExpression) ProjectNode(io.prestosql.spi.plan.ProjectNode) VariableReferenceSymbolConverter.toVariableReference(io.prestosql.sql.planner.VariableReferenceSymbolConverter.toVariableReference) COALESCE(io.prestosql.spi.relation.SpecialForm.Form.COALESCE) Preconditions.checkState(com.google.common.base.Preconditions.checkState) PlanSymbolAllocator(io.prestosql.sql.planner.PlanSymbolAllocator) Captures(io.prestosql.matching.Captures) ValuesNode(io.prestosql.spi.plan.ValuesNode) List(java.util.List) Aggregation(io.prestosql.spi.plan.AggregationNode.Aggregation) DistinctOutputQueryUtil.isDistinct(io.prestosql.sql.planner.optimizations.DistinctOutputQueryUtil.isDistinct) Capture(io.prestosql.matching.Capture) PlanNodeIdAllocator(io.prestosql.spi.plan.PlanNodeIdAllocator) RowExpression(io.prestosql.spi.relation.RowExpression) Optional(java.util.Optional) ValuesNode(io.prestosql.spi.plan.ValuesNode) ImmutableList(com.google.common.collect.ImmutableList) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Symbol(io.prestosql.spi.plan.Symbol) ConstantExpression(io.prestosql.spi.relation.ConstantExpression) RowExpression(io.prestosql.spi.relation.RowExpression) AggregationNode(io.prestosql.spi.plan.AggregationNode) ImmutableMap(com.google.common.collect.ImmutableMap) Aggregation(io.prestosql.spi.plan.AggregationNode.Aggregation) AggregationNode.globalAggregation(io.prestosql.spi.plan.AggregationNode.globalAggregation) Aggregation(io.prestosql.spi.plan.AggregationNode.Aggregation) VariableReferenceExpression(io.prestosql.spi.relation.VariableReferenceExpression) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) CallExpression(io.prestosql.spi.relation.CallExpression)

Example 19 with ValuesNode

use of io.prestosql.spi.plan.ValuesNode in project hetu-core by openlookeng.

the class TransformCorrelatedSingleRowSubqueryToProject method apply.

@Override
public Result apply(LateralJoinNode parent, Captures captures, Context context) {
    List<ValuesNode> values = searchFrom(parent.getSubquery(), context.getLookup()).recurseOnlyWhen(ProjectNode.class::isInstance).where(ValuesNode.class::isInstance).findAll();
    if (values.size() != 1 || !isSingleRowValuesWithNoColumns(values.get(0))) {
        return Result.empty();
    }
    List<ProjectNode> subqueryProjections = searchFrom(parent.getSubquery(), context.getLookup()).where(node -> node instanceof ProjectNode && !node.getOutputSymbols().equals(parent.getCorrelation())).findAll();
    if (subqueryProjections.size() == 0) {
        return Result.ofPlanNode(parent.getInput());
    }
    if (subqueryProjections.size() == 1) {
        Assignments assignments = Assignments.builder().putAll(AssignmentUtils.identityAsSymbolReferences(parent.getInput().getOutputSymbols())).putAll(subqueryProjections.get(0).getAssignments()).build();
        return Result.ofPlanNode(projectNode(parent.getInput(), assignments, context));
    }
    return Result.empty();
}
Also used : AssignmentUtils(io.prestosql.sql.planner.plan.AssignmentUtils) Patterns.lateralJoin(io.prestosql.sql.planner.plan.Patterns.lateralJoin) LateralJoin.filter(io.prestosql.sql.planner.plan.Patterns.LateralJoin.filter) Assignments(io.prestosql.spi.plan.Assignments) Rule(io.prestosql.sql.planner.iterative.Rule) LateralJoinNode(io.prestosql.sql.planner.plan.LateralJoinNode) Pattern(io.prestosql.matching.Pattern) PlanNode(io.prestosql.spi.plan.PlanNode) ProjectNode(io.prestosql.spi.plan.ProjectNode) TRUE_LITERAL(io.prestosql.sql.tree.BooleanLiteral.TRUE_LITERAL) PlanNodeSearcher.searchFrom(io.prestosql.sql.planner.optimizations.PlanNodeSearcher.searchFrom) Captures(io.prestosql.matching.Captures) ValuesNode(io.prestosql.spi.plan.ValuesNode) List(java.util.List) ValuesNode(io.prestosql.spi.plan.ValuesNode) Assignments(io.prestosql.spi.plan.Assignments) ProjectNode(io.prestosql.spi.plan.ProjectNode)

Example 20 with ValuesNode

use of io.prestosql.spi.plan.ValuesNode in project hetu-core by openlookeng.

the class RelationPlanner method visitUnnest.

@Override
protected RelationPlan visitUnnest(Unnest node, Void context) {
    Scope scope = analysis.getScope(node);
    ImmutableList.Builder<Symbol> outputSymbolsBuilder = ImmutableList.builder();
    for (Field field : scope.getRelationType().getVisibleFields()) {
        Symbol symbol = planSymbolAllocator.newSymbol(field);
        outputSymbolsBuilder.add(symbol);
    }
    List<Symbol> unnestedSymbols = outputSymbolsBuilder.build();
    // If we got here, then we must be unnesting a constant, and not be in a join (where there could be column references)
    ImmutableList.Builder<Symbol> argumentSymbols = ImmutableList.builder();
    ImmutableList.Builder<RowExpression> values = ImmutableList.builder();
    ImmutableMap.Builder<Symbol, List<Symbol>> unnestSymbols = ImmutableMap.builder();
    Iterator<Symbol> unnestedSymbolsIterator = unnestedSymbols.iterator();
    for (Expression expression : node.getExpressions()) {
        Type type = analysis.getType(expression);
        Expression rewritten = Coercer.addCoercions(expression, analysis);
        rewritten = ExpressionTreeRewriter.rewriteWith(new ParameterRewriter(analysis.getParameters(), analysis), rewritten);
        values.add(castToRowExpression(rewritten));
        Symbol inputSymbol = planSymbolAllocator.newSymbol(rewritten, type);
        argumentSymbols.add(inputSymbol);
        if (type instanceof ArrayType) {
            Type elementType = ((ArrayType) type).getElementType();
            if (elementType instanceof RowType) {
                ImmutableList.Builder<Symbol> unnestSymbolBuilder = ImmutableList.builder();
                for (int i = 0; i < ((RowType) elementType).getFields().size(); i++) {
                    unnestSymbolBuilder.add(unnestedSymbolsIterator.next());
                }
                unnestSymbols.put(inputSymbol, unnestSymbolBuilder.build());
            } else {
                unnestSymbols.put(inputSymbol, ImmutableList.of(unnestedSymbolsIterator.next()));
            }
        } else if (type instanceof MapType) {
            unnestSymbols.put(inputSymbol, ImmutableList.of(unnestedSymbolsIterator.next(), unnestedSymbolsIterator.next()));
        } else {
            throw new IllegalArgumentException("Unsupported type for UNNEST: " + type);
        }
    }
    Optional<Symbol> ordinalitySymbol = node.isWithOrdinality() ? Optional.of(unnestedSymbolsIterator.next()) : Optional.empty();
    checkState(!unnestedSymbolsIterator.hasNext(), "Not all output symbols were matched with input symbols");
    ValuesNode valuesNode = new ValuesNode(idAllocator.getNextId(), argumentSymbols.build(), ImmutableList.of(values.build()));
    UnnestNode unnestNode = new UnnestNode(idAllocator.getNextId(), valuesNode, ImmutableList.of(), unnestSymbols.build(), ordinalitySymbol);
    return new RelationPlan(unnestNode, scope, unnestedSymbols);
}
Also used : ValuesNode(io.prestosql.spi.plan.ValuesNode) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) Symbol(io.prestosql.spi.plan.Symbol) OriginalExpressionUtils.castToRowExpression(io.prestosql.sql.relational.OriginalExpressionUtils.castToRowExpression) RowExpression(io.prestosql.spi.relation.RowExpression) RowType(io.prestosql.spi.type.RowType) ImmutableMap(com.google.common.collect.ImmutableMap) MapType(io.prestosql.spi.type.MapType) ArrayType(io.prestosql.spi.type.ArrayType) Field(io.prestosql.sql.analyzer.Field) RowType(io.prestosql.spi.type.RowType) MapType(io.prestosql.spi.type.MapType) Type(io.prestosql.spi.type.Type) ArrayType(io.prestosql.spi.type.ArrayType) RelationType(io.prestosql.sql.analyzer.RelationType) Scope(io.prestosql.sql.analyzer.Scope) OriginalExpressionUtils.castToRowExpression(io.prestosql.sql.relational.OriginalExpressionUtils.castToRowExpression) ComparisonExpression(io.prestosql.sql.tree.ComparisonExpression) Expression(io.prestosql.sql.tree.Expression) CoalesceExpression(io.prestosql.sql.tree.CoalesceExpression) RowExpression(io.prestosql.spi.relation.RowExpression) UnnestNode(io.prestosql.sql.planner.plan.UnnestNode) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList)

Aggregations

ValuesNode (io.prestosql.spi.plan.ValuesNode)26 Symbol (io.prestosql.spi.plan.Symbol)16 Test (org.testng.annotations.Test)12 PlanNode (io.prestosql.spi.plan.PlanNode)8 RowExpression (io.prestosql.spi.relation.RowExpression)8 List (java.util.List)8 ImmutableList (com.google.common.collect.ImmutableList)6 JoinNode (io.prestosql.spi.plan.JoinNode)6 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)5 ProjectNode (io.prestosql.spi.plan.ProjectNode)5 MultiJoinNode (io.prestosql.sql.planner.iterative.rule.ReorderJoins.MultiJoinNode)5 MultiJoinNode.toMultiJoinNode (io.prestosql.sql.planner.iterative.rule.ReorderJoins.MultiJoinNode.toMultiJoinNode)5 PlanBuilder (io.prestosql.sql.planner.iterative.rule.test.PlanBuilder)5 ImmutableMap (com.google.common.collect.ImmutableMap)4 ConstantExpression (io.prestosql.spi.relation.ConstantExpression)4 ComparisonExpression (io.prestosql.sql.tree.ComparisonExpression)4 Session (io.prestosql.Session)3 OutputNode (io.prestosql.sql.planner.plan.OutputNode)3 OriginalExpressionUtils.castToRowExpression (io.prestosql.sql.relational.OriginalExpressionUtils.castToRowExpression)3 Expression (io.prestosql.sql.tree.Expression)3