@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); }
private PlanNode createOutputPlan(RelationPlan plan, Analysis analysis) { ImmutableList.Builder<Symbol> outputs = ImmutableList.builder(); ImmutableList.Builder<String> names = ImmutableList.builder(); int columnNumber = 0; RelationType outputDescriptor = analysis.getOutputDescriptor(); for (Field field : outputDescriptor.getVisibleFields()) { String name = field.getName().orElse("_col" + columnNumber); names.add(name); int fieldIndex = outputDescriptor.indexOf(field); Symbol symbol = plan.getSymbol(fieldIndex); outputs.add(symbol); columnNumber++; } return new OutputNode(idAllocator.getNextId(), plan.getRoot(), names.build(), outputs.build()); }
public RelationPlan(PlanNode root, Scope scope, List<Symbol> fieldMappings) { requireNonNull(root, "root is null"); requireNonNull(fieldMappings, "outputSymbols is null"); requireNonNull(scope, "scope is null"); int allFieldCount = getAllFieldCount(scope); checkArgument(allFieldCount == fieldMappings.size(), "Number of outputs (%s) doesn't match number of fields in scopes tree (%s)", fieldMappings.size(), allFieldCount); this.root = root; this.scope = scope; this.fieldMappings = ImmutableList.copyOf(fieldMappings); }
private Optional<Symbol> getSymbol(RelationPlan plan, Expression expression) { if (!analysis.isColumnReference(expression)) { // Expression can be a reference to lambda argument (or DereferenceExpression based on lambda argument reference). // In such case, the expression might still be resolvable with plan.getScope() but we should not resolve it. return Optional.empty(); } return plan.getScope() .tryResolveField(expression) .filter(ResolvedField::isLocal) .map(field -> requireNonNull(plan.getFieldMappings().get(field.getHierarchyFieldIndex()))); } }
private PlanBuilder createPlanBuilder(Node node) { RelationPlan relationPlan = new RelationPlanner(analysis, symbolAllocator, idAllocator, lambdaDeclarationToSymbolMap, metadata, session) .process(node, null); TranslationMap translations = new TranslationMap(relationPlan, analysis, lambdaDeclarationToSymbolMap); // Make field->symbol mapping from underlying relation plan available for translations // This makes it possible to rewrite FieldOrExpressions that reference fields from the FROM clause directly translations.setFieldMappings(relationPlan.getFieldMappings()); if (node instanceof Expression && relationPlan.getFieldMappings().size() == 1) { translations.put((Expression) node, getOnlyElement(relationPlan.getFieldMappings())); } return new PlanBuilder(translations, relationPlan.getRoot(), analysis.getParameters()); }
public void put(Expression expression, Symbol symbol) { if (expression instanceof FieldReference) { int fieldIndex = ((FieldReference) expression).getFieldIndex(); fieldSymbols[fieldIndex] = symbol; expressionToSymbols.put(rewriteBase.getSymbol(fieldIndex).toSymbolReference(), symbol); return; } Expression translated = translateNamesToSymbols(expression); expressionToSymbols.put(translated, symbol); // also update the field mappings if this expression is a field reference rewriteBase.getScope().tryResolveField(expression) .filter(ResolvedField::isLocal) .ifPresent(field -> fieldSymbols[field.getHierarchyFieldIndex()] = symbol); }
@Override protected RelationPlan visitAliasedRelation(AliasedRelation node, Void context) { RelationPlan subPlan = process(node.getRelation(), context); RelationType outputDescriptor = analysis.getOutputDescriptor(node); return new RelationPlan(subPlan.getRoot(), outputDescriptor, subPlan.getOutputSymbols(), subPlan.getSampleWeight()); }
@Override protected RelationPlan visitSampledRelation(SampledRelation node, Void context) { RelationPlan subPlan = process(node.getRelation(), context); double ratio = analysis.getSampleRatio(node); PlanNode planNode = new SampleNode(idAllocator.getNextId(), subPlan.getRoot(), ratio, SampleNode.Type.fromType(node.getType())); return new RelationPlan(planNode, analysis.getScope(node), subPlan.getFieldMappings()); }
private RelationPlan planImplicitTable() { List<Expression> emptyRow = ImmutableList.of(); Scope scope = Scope.create(); return new RelationPlan( new ValuesNode(idAllocator.getNextId(), ImmutableList.of(), ImmutableList.of(emptyRow)), scope, ImmutableList.of()); }
assignments.put(output, plan.getSymbol(index).toQualifiedNameReference()); ProjectNode projectNode = new ProjectNode(idAllocator.getNextId(), plan.getRoot(), assignments.build()); .collect(toImmutableList())); plan = new RelationPlan( projectNode, tupleDescriptor, projectNode.getOutputSymbols(), plan.getSampleWeight());
private PlanBuilder initializePlanBuilder(RelationPlan relationPlan) { TranslationMap translations = new TranslationMap(relationPlan, analysis); // Make field->symbol mapping from underlying relation plan available for translations // This makes it possible to rewrite FieldOrExpressions that reference fields from the underlying tuple directly translations.setFieldMappings(relationPlan.getOutputSymbols()); return new PlanBuilder(translations, relationPlan.getRoot(), relationPlan.getSampleWeight()); }
Symbol input = plan.getSymbol(index); Type tableType = column.getType(); Type queryType = symbolAllocator.getTypes().get(input); ProjectNode projectNode = new ProjectNode(idAllocator.getNextId(), plan.getRoot(), assignments.build()); Scope scope = Scope.builder().withRelationType(RelationId.anonymous(), new RelationType(fields)).build(); plan = new RelationPlan(projectNode, scope, projectNode.getOutputSymbols());
List<Symbol> childOutputSymbols = relationPlan.getFieldMappings(); if (outputs == null) { RelationType descriptor = relationPlan.getDescriptor(); ImmutableList.Builder<Symbol> outputSymbolBuilder = ImmutableList.builder(); for (Field field : descriptor.getVisibleFields()) { RelationType descriptor = relationPlan.getDescriptor(); checkArgument(descriptor.getVisibleFieldCount() == outputs.size(), "Expected relation to have %s symbols but has %s symbols", sources.add(relationPlan.getRoot());
private RelationPlan planLateralJoin(Join join, RelationPlan leftPlan, Lateral lateral) { RelationPlan rightPlan = process(lateral.getQuery(), null); PlanBuilder leftPlanBuilder = initializePlanBuilder(leftPlan); PlanBuilder rightPlanBuilder = initializePlanBuilder(rightPlan); PlanBuilder planBuilder = subqueryPlanner.appendLateralJoin(leftPlanBuilder, rightPlanBuilder, lateral.getQuery(), true, LateralJoinNode.Type.INNER); List<Symbol> outputSymbols = ImmutableList.<Symbol>builder() .addAll(leftPlan.getRoot().getOutputSymbols()) .addAll(rightPlan.getRoot().getOutputSymbols()) .build(); return new RelationPlan(planBuilder.getRoot(), analysis.getScope(join), outputSymbols); }
@Override protected RelationPlan visitSampledRelation(SampledRelation node, Void context) { if (node.getColumnsToStratifyOn().isPresent()) { throw new UnsupportedOperationException("STRATIFY ON is not yet implemented"); } RelationPlan subPlan = process(node.getRelation(), context); RelationType outputDescriptor = analysis.getOutputDescriptor(node); double ratio = analysis.getSampleRatio(node); Symbol sampleWeightSymbol = null; if (node.getType() == SampledRelation.Type.POISSONIZED) { sampleWeightSymbol = symbolAllocator.newSymbol("$sampleWeight", BIGINT); } PlanNode planNode = new SampleNode(idAllocator.getNextId(), subPlan.getRoot(), ratio, SampleNode.Type.fromType(node.getType()), node.isRescaled(), Optional.ofNullable(sampleWeightSymbol)); return new RelationPlan(planNode, outputDescriptor, subPlan.getOutputSymbols(), Optional.ofNullable(sampleWeightSymbol)); }
checkState(!unnestedSymbolsIterator.hasNext(), "Not all output symbols were matched with input symbols"); UnnestNode unnestNode = new UnnestNode(idAllocator.getNextId(), projectNode, leftPlan.getFieldMappings(), unnestSymbols.build(), ordinalitySymbol); return new RelationPlan(unnestNode, analysis.getScope(joinNode), unnestNode.getOutputSymbols());
checkState(!unnestedSymbolsIterator.hasNext(), "Not all output symbols were matched with input symbols"); UnnestNode unnestNode = new UnnestNode(idAllocator.getNextId(), projectNode, leftPlan.getOutputSymbols(), unnestSymbols.build(), ordinalitySymbol); return new RelationPlan(unnestNode, outputDescriptor, unnestNode.getOutputSymbols(), Optional.empty());
private Expression rewriteExpressionWithResolvedName(Expression node) { return getSymbol(rewriteBase, node) .map(symbol -> coerceIfNecessary(node, symbol.toSymbolReference())) .orElse(coerceIfNecessary(node, node)); }
private static List<ColumnMetadata> getOutputTableColumns(RelationPlan plan, Optional<List<Identifier>> columnAliases) { ImmutableList.Builder<ColumnMetadata> columns = ImmutableList.builder(); int aliasPosition = 0; for (Field field : plan.getDescriptor().getVisibleFields()) { String columnName = columnAliases.isPresent() ? columnAliases.get().get(aliasPosition).getValue() : field.getName().get(); columns.add(new ColumnMetadata(columnName, field.getType())); aliasPosition++; } return columns.build(); }
private PlanBuilder appendScalarSubqueryJoin(PlanBuilder builder, SubqueryExpression scalarSubquery) { EnforceSingleRowNode enforceSingleRowNode = new EnforceSingleRowNode(idAllocator.getNextId(), createRelationPlan(scalarSubquery).getRoot()); TranslationMap translations = copyTranslations(builder); translations.put(scalarSubquery, getOnlyElement(enforceSingleRowNode.getOutputSymbols())); // Cross join current (root) relation with subquery PlanNode root = builder.getRoot(); if (root.getOutputSymbols().isEmpty()) { // there is nothing to join with - e.g. SELECT (SELECT 1) return new PlanBuilder(translations, enforceSingleRowNode, builder.getSampleWeight()); } else { return new PlanBuilder(translations, new JoinNode(idAllocator.getNextId(), JoinNode.Type.FULL, root, enforceSingleRowNode, ImmutableList.of(), Optional.empty(), Optional.empty()), builder.getSampleWeight()); } }