public Builder putAll(Map<Symbol, Expression> assignments) { for (Entry<Symbol, Expression> assignment : assignments.entrySet()) { put(assignment.getKey(), assignment.getValue()); } return this; }
public Builder put(Entry<Symbol, Expression> assignment) { put(assignment.getKey(), assignment.getValue()); return this; }
private Collector<Entry<Symbol, Expression>, Builder, Assignments> toAssignments() { return Collector.of( Assignments::builder, (builder, entry) -> builder.put(entry.getKey(), entry.getValue()), (left, right) -> { left.putAll(right.build()); return left; }, Assignments.Builder::build); }
private PlanBuilder explicitCoercionFields(PlanBuilder subPlan, Iterable<Expression> alreadyCoerced, Iterable<? extends Expression> uncoerced) { TranslationMap translations = new TranslationMap(subPlan.getRelationPlan(), analysis, lambdaDeclarationToSymbolMap); Assignments.Builder projections = Assignments.builder(); projections.putAll(coerce(uncoerced, subPlan, translations)); for (Expression expression : alreadyCoerced) { if (expression instanceof SymbolReference) { // If this is an identity projection, no need to rewrite it // This is needed because certain synthetic identity expressions such as "group id" introduced when planning GROUPING // don't have a corresponding analysis, so the code below doesn't work for them projections.put(Symbol.from(expression), expression); continue; } Symbol symbol = symbolAllocator.newSymbol(expression, analysis.getType(expression)); Expression rewritten = subPlan.rewrite(expression); projections.put(symbol, rewritten); translations.put(expression, symbol); } return new PlanBuilder(translations, new ProjectNode( idAllocator.getNextId(), subPlan.getRoot(), projections.build()), analysis.getParameters()); }
@Override protected RelationPlan visitAliasedRelation(AliasedRelation node, Void context) { RelationPlan subPlan = process(node.getRelation(), context); PlanNode root = subPlan.getRoot(); List<Symbol> mappings = subPlan.getFieldMappings(); if (node.getColumnNames() != null) { ImmutableList.Builder<Symbol> newMappings = ImmutableList.<Symbol>builder(); Assignments.Builder assignments = Assignments.builder(); // project only the visible columns from the underlying relation for (int i = 0; i < subPlan.getDescriptor().getAllFieldCount(); i++) { Field field = subPlan.getDescriptor().getFieldByIndex(i); if (!field.isHidden()) { Symbol aliasedColumn = symbolAllocator.newSymbol(field); assignments.put(aliasedColumn, subPlan.getFieldMappings().get(i).toSymbolReference()); newMappings.add(aliasedColumn); } } root = new ProjectNode(idAllocator.getNextId(), subPlan.getRoot(), assignments.build()); mappings = newMappings.build(); } return new RelationPlan(root, analysis.getScope(node), mappings); }
public PlanNode rewriteScalarAggregation(LateralJoinNode lateralJoinNode, AggregationNode aggregation) { List<Symbol> correlation = lateralJoinNode.getCorrelation(); Optional<DecorrelatedNode> source = planNodeDecorrelator.decorrelateFilters(lookup.resolve(aggregation.getSource()), correlation); if (!source.isPresent()) { return lateralJoinNode; } Symbol nonNull = symbolAllocator.newSymbol("non_null", BooleanType.BOOLEAN); Assignments scalarAggregationSourceAssignments = Assignments.builder() .putIdentities(source.get().getNode().getOutputSymbols()) .put(nonNull, TRUE_LITERAL) .build(); ProjectNode scalarAggregationSourceWithNonNullableSymbol = new ProjectNode( idAllocator.getNextId(), source.get().getNode(), scalarAggregationSourceAssignments); return rewriteScalarAggregation( lateralJoinNode, aggregation, scalarAggregationSourceWithNonNullableSymbol, source.get().getCorrelatedPredicates(), nonNull); }
public PlanBuilder appendProjections(Iterable<Expression> expressions, SymbolAllocator symbolAllocator, PlanNodeIdAllocator idAllocator) { TranslationMap translations = copyTranslations(); Assignments.Builder projections = Assignments.builder(); // add an identity projection for underlying plan for (Symbol symbol : getRoot().getOutputSymbols()) { projections.put(symbol, symbol.toSymbolReference()); } ImmutableMap.Builder<Symbol, Expression> newTranslations = ImmutableMap.builder(); for (Expression expression : expressions) { Symbol symbol = symbolAllocator.newSymbol(expression, getAnalysis().getTypeWithCoercions(expression)); projections.put(symbol, translations.rewrite(expression)); newTranslations.put(symbol, expression); } // Now append the new translations into the TranslationMap for (Map.Entry<Symbol, Expression> entry : newTranslations.build().entrySet()) { translations.put(entry.getValue(), entry.getKey()); } return new PlanBuilder(translations, new ProjectNode(idAllocator.getNextId(), getRoot(), projections.build()), parameters); } }
private PlanBuilder project(PlanBuilder subPlan, Iterable<Expression> expressions) { TranslationMap outputTranslations = new TranslationMap(subPlan.getRelationPlan(), analysis, lambdaDeclarationToSymbolMap); Assignments.Builder projections = Assignments.builder(); for (Expression expression : expressions) { if (expression instanceof SymbolReference) { Symbol symbol = Symbol.from(expression); projections.put(symbol, expression); outputTranslations.put(expression, symbol); continue; } Symbol symbol = symbolAllocator.newSymbol(expression, analysis.getTypeWithCoercions(expression)); projections.put(symbol, subPlan.rewrite(expression)); outputTranslations.put(expression, symbol); } return new PlanBuilder(outputTranslations, new ProjectNode( idAllocator.getNextId(), subPlan.getRoot(), projections.build()), analysis.getParameters()); }
@Test public void testDoesNotFireNarrowingProjection() { tester().assertThat(new PushProjectionThroughExchange()) .on(p -> { Symbol a = p.symbol("a"); Symbol b = p.symbol("b"); Symbol c = p.symbol("c"); return p.project( Assignments.builder() .put(a, a.toSymbolReference()) .put(b, b.toSymbolReference()) .build(), p.exchange(e -> e .addSource(p.values(a, b, c)) .addInputsSet(a, b, c) .singleDistributionPartitioningScheme(a, b, c))); }) .doesNotFire(); }
private static PlanNode addPartitioningNodes(Context context, PlanNode node, Symbol partitionSymbol, KdbTree kdbTree, Expression geometry, Optional<Expression> radius) { Assignments.Builder projections = Assignments.builder(); for (Symbol outputSymbol : node.getOutputSymbols()) { projections.putIdentity(outputSymbol); } ImmutableList.Builder<Expression> partitioningArguments = ImmutableList.<Expression>builder() .add(new Cast(new StringLiteral(KdbTreeUtils.toJson(kdbTree)), KDB_TREE_TYPENAME)) .add(geometry); radius.map(partitioningArguments::add); FunctionCall partitioningFunction = new FunctionCall(QualifiedName.of("spatial_partitions"), partitioningArguments.build()); Symbol partitionsSymbol = context.getSymbolAllocator().newSymbol(partitioningFunction, new ArrayType(INTEGER)); projections.put(partitionsSymbol, partitioningFunction); return new UnnestNode( context.getIdAllocator().getNextId(), new ProjectNode(context.getIdAllocator().getNextId(), node, projections.build()), node.getOutputSymbols(), ImmutableMap.of(partitionsSymbol, ImmutableList.of(partitionSymbol)), Optional.empty()); }
@Override public MatchResult visitExchange(ExchangeNode node, PlanMatchPattern pattern) { List<List<Symbol>> allInputs = node.getInputs(); List<Symbol> outputs = node.getOutputSymbols(); MatchResult result = super.visitExchange(node, pattern); if (!result.isMatch()) { return result; } SymbolAliases newAliases = result.getAliases(); for (List<Symbol> inputs : allInputs) { Assignments.Builder assignments = Assignments.builder(); for (int i = 0; i < inputs.size(); ++i) { assignments.put(outputs.get(i), inputs.get(i).toSymbolReference()); } newAliases = newAliases.updateAssignments(assignments.build()); } return match(newAliases); }
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "type of symbol 'expr(_[0-9]+)?' is expected to be bigint, but the actual type is integer") public void testInvalidProject() { Expression expression1 = new Cast(columnB.toSymbolReference(), StandardTypes.INTEGER); Expression expression2 = new Cast(columnA.toSymbolReference(), StandardTypes.INTEGER); Assignments assignments = Assignments.builder() .put(symbolAllocator.newSymbol(expression1, BIGINT), expression1) // should be INTEGER .put(symbolAllocator.newSymbol(expression1, INTEGER), expression2) .build(); PlanNode node = new ProjectNode( newId(), baseTableScan, assignments); assertTypesValid(node); }
private PlanNode appendMarkers(PlanNode source, int markerIndex, List<Symbol> markers, Map<Symbol, SymbolReference> projections) { Assignments.Builder assignments = Assignments.builder(); // add existing intersect symbols to projection for (Map.Entry<Symbol, SymbolReference> entry : projections.entrySet()) { Symbol symbol = symbolAllocator.newSymbol(entry.getKey().getName(), symbolAllocator.getTypes().get(entry.getKey())); assignments.put(symbol, entry.getValue()); } // add extra marker fields to the projection for (int i = 0; i < markers.size(); ++i) { Expression expression = (i == markerIndex) ? TRUE_LITERAL : new Cast(new NullLiteral(), StandardTypes.BOOLEAN); assignments.put(symbolAllocator.newSymbol(markers.get(i).getName(), BOOLEAN), expression); } return new ProjectNode(idAllocator.getNextId(), source, assignments.build()); }
@Test public void testValidProject() { Expression expression1 = new Cast(columnB.toSymbolReference(), StandardTypes.BIGINT); Expression expression2 = new Cast(columnC.toSymbolReference(), StandardTypes.BIGINT); Assignments assignments = Assignments.builder() .put(symbolAllocator.newSymbol(expression1, BIGINT), expression1) .put(symbolAllocator.newSymbol(expression2, BIGINT), expression2) .build(); PlanNode node = new ProjectNode( newId(), baseTableScan, assignments); assertTypesValid(node); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Set<Symbol>> context) { ImmutableSet.Builder<Symbol> expectedInputs = ImmutableSet.builder(); Assignments.Builder builder = Assignments.builder(); node.getAssignments().forEach((symbol, expression) -> { if (context.get().contains(symbol)) { expectedInputs.addAll(SymbolsExtractor.extractUnique(expression)); builder.put(symbol, expression); } }); PlanNode source = context.rewrite(node.getSource(), expectedInputs.build()); return new ProjectNode(node.getId(), source, builder.build()); }
public static Assignments of(Symbol symbol, Expression expression) { return builder().put(symbol, expression).build(); }
public Builder putIdentity(Symbol symbol) { put(symbol, symbol.toSymbolReference()); return this; }
private static PlanNode addProjection(Context context, PlanNode node, Symbol symbol, Expression expression) { Assignments.Builder projections = Assignments.builder(); for (Symbol outputSymbol : node.getOutputSymbols()) { projections.putIdentity(outputSymbol); } projections.put(symbol, expression); return new ProjectNode(context.getIdAllocator().getNextId(), node, projections.build()); }
@Test public void testValidTypeOnlyCoercion() { Expression expression = new Cast(columnB.toSymbolReference(), StandardTypes.BIGINT); Assignments assignments = Assignments.builder() .put(symbolAllocator.newSymbol(expression, BIGINT), expression) .put(symbolAllocator.newSymbol(columnE.toSymbolReference(), VARCHAR), columnE.toSymbolReference()) // implicit coercion from varchar(3) to varchar .build(); PlanNode node = new ProjectNode(newId(), baseTableScan, assignments); assertTypesValid(node); }