@Override public PlanNode visitUnnest(UnnestNode node, RewriteContext<Set<Symbol>> context) { List<Symbol> replicateSymbols = node.getReplicateSymbols().stream() .filter(context.get()::contains) .collect(toImmutableList()); Optional<Symbol> ordinalitySymbol = node.getOrdinalitySymbol(); if (ordinalitySymbol.isPresent() && !context.get().contains(ordinalitySymbol.get())) { ordinalitySymbol = Optional.empty(); } Map<Symbol, List<Symbol>> unnestSymbols = node.getUnnestSymbols(); ImmutableSet.Builder<Symbol> expectedInputs = ImmutableSet.<Symbol>builder() .addAll(replicateSymbols) .addAll(unnestSymbols.keySet()); PlanNode source = context.rewrite(node.getSource(), expectedInputs.build()); return new UnnestNode(node.getId(), source, replicateSymbols, unnestSymbols, ordinalitySymbol); }
@JsonCreator public OutputNode(@JsonProperty("id") PlanNodeId id, @JsonProperty("source") PlanNode source, @JsonProperty("columns") List<String> columnNames, @JsonProperty("outputs") List<Symbol> outputs) { super(id); requireNonNull(source, "source is null"); requireNonNull(columnNames, "columnNames is null"); Preconditions.checkArgument(columnNames.size() == outputs.size(), "columnNames and assignments sizes don't match"); this.source = source; this.columnNames = columnNames; this.outputs = ImmutableList.copyOf(outputs); }
@Override public ActualProperties visitFilter(FilterNode node, List<ActualProperties> inputProperties) { ActualProperties properties = Iterables.getOnlyElement(inputProperties); DomainTranslator.ExtractionResult decomposedPredicate = DomainTranslator.fromPredicate( metadata, session, node.getPredicate(), types); Map<Symbol, Object> constants = new HashMap<>(properties.getConstants()); Map<Symbol, NullableValue> fixedValues = extractFixedValues(decomposedPredicate.getTupleDomain()).orElse(ImmutableMap.of()); constants.putAll(Maps.transformValues(filterValues(fixedValues, value -> !value.isNull()), NullableValue::getValue)); return ActualProperties.builderFrom(properties) .constants(constants) .build(); }
@JsonCreator public SemiJoinNode(@JsonProperty("id") PlanNodeId id, @JsonProperty("source") PlanNode source, @JsonProperty("filteringSource") PlanNode filteringSource, @JsonProperty("sourceJoinSymbol") Symbol sourceJoinSymbol, @JsonProperty("filteringSourceJoinSymbol") Symbol filteringSourceJoinSymbol, @JsonProperty("semiJoinOutput") Symbol semiJoinOutput, @JsonProperty("sourceHashSymbol") Optional<Symbol> sourceHashSymbol, @JsonProperty("filteringSourceHashSymbol") Optional<Symbol> filteringSourceHashSymbol) { super(id); this.source = requireNonNull(source, "source is null"); this.filteringSource = requireNonNull(filteringSource, "filteringSource is null"); this.sourceJoinSymbol = requireNonNull(sourceJoinSymbol, "sourceJoinSymbol is null"); this.filteringSourceJoinSymbol = requireNonNull(filteringSourceJoinSymbol, "filteringSourceJoinSymbol is null"); this.semiJoinOutput = requireNonNull(semiJoinOutput, "semiJoinOutput is null"); this.sourceHashSymbol = requireNonNull(sourceHashSymbol, "sourceHashSymbol is null"); this.filteringSourceHashSymbol = requireNonNull(filteringSourceHashSymbol, "filteringSourceHashSymbol is null"); }
@Override public PlanWithProperties visitIndexJoin(IndexJoinNode node, Context context) { List<Symbol> joinColumns = Lists.transform(node.getCriteria(), IndexJoinNode.EquiJoinClause::getProbe); // Only prefer grouping on join columns if no parent local property preferences List<LocalProperty<Symbol>> desiredLocalProperties = context.getPreferredProperties().getLocalProperties().isEmpty() ? grouped(joinColumns) : ImmutableList.of(); PlanWithProperties probeSource = node.getProbeSource().accept(this, context.withPreferredProperties(PreferredProperties.derivePreferences(context.getPreferredProperties(), ImmutableSet.copyOf(joinColumns), desiredLocalProperties))); ActualProperties probeProperties = probeSource.getProperties(); PlanWithProperties indexSource = node.getIndexSource().accept(this, context.withPreferredProperties(PreferredProperties.any())); // TODO: allow repartitioning if unpartitioned to increase parallelism if (shouldRepartitionForIndexJoin(joinColumns, context.getPreferredProperties(), probeProperties)) { probeSource = withDerivedProperties( partitionedExchange(idAllocator.getNextId(), probeSource.getNode(), new PartitionFunctionBinding(HASH, joinColumns, node.getProbeHashSymbol())), probeProperties); } // TODO: if input is grouped, create streaming join // index side is really a nested-loops plan, so don't add exchanges PlanNode result = ChildReplacer.replaceChildren(node, ImmutableList.of(probeSource.getNode(), node.getIndexSource())); return new PlanWithProperties(result, deriveProperties(result, ImmutableList.of(probeSource.getProperties(), indexSource.getProperties()))); }
public MockRemoteTask createTableScanTask(TaskId taskId, Node newNode, List<Split> splits, PartitionedSplitCountTracker partitionedSplitCountTracker) { Symbol symbol = new Symbol("column"); PlanNodeId sourceId = new PlanNodeId("sourceId"); PlanFragment testFragment = new PlanFragment( new PlanFragmentId("test"), new TableScanNode( sourceId, new TableHandle("test", new TestingTableHandle()), ImmutableList.of(symbol), ImmutableMap.of(symbol, new TestingColumnHandle("column")), Optional.empty(), TupleDomain.all(), null), ImmutableMap.<Symbol, Type>of(symbol, VARCHAR), ImmutableList.of(symbol), SOURCE, sourceId, Optional.empty()); ImmutableMultimap.Builder<PlanNodeId, Split> initialSplits = ImmutableMultimap.builder(); for (Split sourceSplit : splits) { initialSplits.put(sourceId, sourceSplit); } return createRemoteTask(TEST_SESSION, taskId, newNode, 0, testFragment, initialSplits.build(), OutputBuffers.INITIAL_EMPTY_OUTPUT_BUFFERS, partitionedSplitCountTracker); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Context> context) { // Rewrite the lookup symbols in terms of only the pre-projected symbols that have direct translations Set<Symbol> newLookupSymbols = context.get().getLookupSymbols().stream() .map(node.getAssignments()::get) .filter(QualifiedNameReference.class::isInstance) .map(IndexJoinOptimizer::referenceToSymbol) .collect(toImmutableSet()); if (newLookupSymbols.isEmpty()) { return node; } return context.defaultRewrite(node, new Context(newLookupSymbols, context.get().getSuccess())); }
@Override public PlanNode visitIndexJoin(IndexJoinNode node, RewriteContext<Context> context) { // Lookup symbols can only be passed through the probe side of an index join Set<Symbol> probeLookupSymbols = context.get().getLookupSymbols().stream() .filter(node.getProbeSource().getOutputSymbols()::contains) .collect(toImmutableSet()); if (probeLookupSymbols.isEmpty()) { return node; } PlanNode rewrittenProbeSource = context.rewrite(node.getProbeSource(), new Context(probeLookupSymbols, context.get().getSuccess())); PlanNode source = node; if (rewrittenProbeSource != node.getProbeSource()) { source = new IndexJoinNode(node.getId(), node.getType(), rewrittenProbeSource, node.getIndexSource(), node.getCriteria(), node.getProbeHashSymbol(), node.getIndexHashSymbol()); } return source; }
@Override public Map<Symbol, Symbol> visitProject(ProjectNode node, Set<Symbol> lookupSymbols) { // Map from output Symbols to source Symbols Map<Symbol, Symbol> directSymbolTranslationOutputMap = Maps.transformValues(Maps.filterValues(node.getAssignments(), QualifiedNameReference.class::isInstance), IndexJoinOptimizer::referenceToSymbol); Map<Symbol, Symbol> outputToSourceMap = FluentIterable.from(lookupSymbols) .filter(in(directSymbolTranslationOutputMap.keySet())) .toMap(Functions.forMap(directSymbolTranslationOutputMap)); checkState(!outputToSourceMap.isEmpty(), "No lookup symbols were able to pass through the projection"); // Map from source Symbols to underlying index source Symbols Map<Symbol, Symbol> sourceToIndexMap = node.getSource().accept(this, ImmutableSet.copyOf(outputToSourceMap.values())); // Generate the Map the connects lookup symbols to underlying index source symbols Map<Symbol, Symbol> outputToIndexMap = Maps.transformValues(Maps.filterValues(outputToSourceMap, in(sourceToIndexMap.keySet())), Functions.forMap(sourceToIndexMap)); return ImmutableMap.copyOf(outputToIndexMap); }
@Override public PlanNode visitMarkDistinct(MarkDistinctNode node, RewriteContext<Set<Symbol>> context) { if (!context.get().contains(node.getMarkerSymbol())) { return context.rewrite(node.getSource(), context.get()); } ImmutableSet.Builder<Symbol> expectedInputs = ImmutableSet.<Symbol>builder() .addAll(node.getDistinctSymbols()) .addAll(context.get()); if (node.getHashSymbol().isPresent()) { expectedInputs.add(node.getHashSymbol().get()); } PlanNode source = context.rewrite(node.getSource(), expectedInputs.build()); return new MarkDistinctNode(node.getId(), source, node.getMarkerSymbol(), node.getDistinctSymbols(), node.getHashSymbol()); }
@Override public PlanNode visitIndexJoin(IndexJoinNode node, RewriteContext<Void> context) { PlanNode rewrittenIndex = context.rewrite(node.getIndexSource(), null); PlanNode rewrittenProbe = context.rewrite(node.getProbeSource(), null); Symbol indexHashSymbol = symbolAllocator.newHashSymbol(); Symbol probeHashSymbol = symbolAllocator.newHashSymbol(); List<IndexJoinNode.EquiJoinClause> clauses = node.getCriteria(); List<Symbol> indexSymbols = Lists.transform(clauses, IndexJoinNode.EquiJoinClause::getIndex); List<Symbol> probeSymbols = Lists.transform(clauses, IndexJoinNode.EquiJoinClause::getProbe); PlanNode indexHashProjectNode = getHashProjectNode(idAllocator, rewrittenIndex, indexHashSymbol, indexSymbols); PlanNode probeHashProjectNode = getHashProjectNode(idAllocator, rewrittenProbe, probeHashSymbol, probeSymbols); return new IndexJoinNode(idAllocator.getNextId(), node.getType(), probeHashProjectNode, indexHashProjectNode, node.getCriteria(), Optional.of(probeHashSymbol), Optional.of(indexHashSymbol)); }
@JsonCreator public IndexSourceNode( @JsonProperty("id") PlanNodeId id, @JsonProperty("indexHandle") IndexHandle indexHandle, @JsonProperty("tableHandle") TableHandle tableHandle, @JsonProperty("lookupSymbols") Set<Symbol> lookupSymbols, @JsonProperty("outputSymbols") List<Symbol> outputSymbols, @JsonProperty("assignments") Map<Symbol, ColumnHandle> assignments, @JsonProperty("effectiveTupleDomain") TupleDomain<ColumnHandle> effectiveTupleDomain) { super(id); this.indexHandle = requireNonNull(indexHandle, "indexHandle is null"); this.tableHandle = requireNonNull(tableHandle, "tableHandle is null"); this.lookupSymbols = ImmutableSet.copyOf(requireNonNull(lookupSymbols, "lookupSymbols is null")); this.outputSymbols = ImmutableList.copyOf(requireNonNull(outputSymbols, "outputSymbols is null")); this.assignments = ImmutableMap.copyOf(requireNonNull(assignments, "assignments is null")); this.effectiveTupleDomain = requireNonNull(effectiveTupleDomain, "effectiveTupleDomain is null"); checkArgument(!lookupSymbols.isEmpty(), "lookupSymbols is empty"); checkArgument(!outputSymbols.isEmpty(), "outputSymbols is empty"); checkArgument(assignments.keySet().containsAll(lookupSymbols), "Assignments do not include all lookup symbols"); checkArgument(outputSymbols.containsAll(lookupSymbols), "Lookup symbols need to be part of the output symbols"); }
@JsonCreator public TopNNode(@JsonProperty("id") PlanNodeId id, @JsonProperty("source") PlanNode source, @JsonProperty("count") long count, @JsonProperty("orderBy") List<Symbol> orderBy, @JsonProperty("orderings") Map<Symbol, SortOrder> orderings, @JsonProperty("partial") boolean partial) { super(id); requireNonNull(source, "source is null"); Preconditions.checkArgument(count >= 0, "count must be positive"); requireNonNull(orderBy, "orderBy is null"); Preconditions.checkArgument(!orderBy.isEmpty(), "orderBy is empty"); Preconditions.checkArgument(orderings.size() == orderBy.size(), "orderBy and orderings sizes don't match"); this.source = source; this.count = count; this.orderBy = ImmutableList.copyOf(orderBy); this.orderings = ImmutableMap.copyOf(orderings); this.partial = partial; }
@Override public PlanNode visitIndexJoin(IndexJoinNode node, RewriteContext<Set<Symbol>> context) { ImmutableSet.Builder<Symbol> probeInputsBuilder = ImmutableSet.builder(); probeInputsBuilder.addAll(context.get()) .addAll(Iterables.transform(node.getCriteria(), IndexJoinNode.EquiJoinClause::getProbe)); if (node.getProbeHashSymbol().isPresent()) { probeInputsBuilder.add(node.getProbeHashSymbol().get()); } Set<Symbol> probeInputs = probeInputsBuilder.build(); ImmutableSet.Builder<Symbol> indexInputBuilder = ImmutableSet.builder(); indexInputBuilder.addAll(context.get()) .addAll(Iterables.transform(node.getCriteria(), IndexJoinNode.EquiJoinClause::getIndex)); if (node.getIndexHashSymbol().isPresent()) { indexInputBuilder.add(node.getIndexHashSymbol().get()); } Set<Symbol> indexInputs = indexInputBuilder.build(); PlanNode probeSource = context.rewrite(node.getProbeSource(), probeInputs); PlanNode indexSource = context.rewrite(node.getIndexSource(), indexInputs); return new IndexJoinNode(node.getId(), node.getType(), probeSource, indexSource, node.getCriteria(), node.getProbeHashSymbol(), node.getIndexHashSymbol()); }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); Map<Symbol, Expression> assignments = ImmutableMap.copyOf(Maps.transformValues(node.getAssignments(), CanonicalizeExpressions::canonicalizeExpression)); return new ProjectNode(node.getId(), source, assignments); }
@Override public PlanNode optimize(PlanNode plan, Session session, Map<Symbol, Type> types, SymbolAllocator symbolAllocator, PlanNodeIdAllocator idAllocator) { requireNonNull(plan, "plan is null"); requireNonNull(session, "session is null"); requireNonNull(types, "types is null"); requireNonNull(symbolAllocator, "symbolAllocator is null"); requireNonNull(idAllocator, "idAllocator is null"); return SimplePlanRewriter.rewriteWith(new Rewriter(), plan); }
@Override public PlanNode visitAggregation(AggregationNode node, RewriteContext<Void> context) { Map<Symbol, FunctionCall> aggregations = new LinkedHashMap<>(node.getAggregations()); Map<Symbol, Signature> functions = new LinkedHashMap<>(node.getFunctions()); PlanNode source = context.rewrite(node.getSource()); if (source instanceof ProjectNode) { ProjectNode projectNode = (ProjectNode) source; for (Entry<Symbol, FunctionCall> entry : node.getAggregations().entrySet()) { Symbol symbol = entry.getKey(); FunctionCall functionCall = entry.getValue(); Signature signature = node.getFunctions().get(symbol); if (isCountConstant(projectNode, functionCall, signature)) { aggregations.put(symbol, new FunctionCall(functionCall.getName(), functionCall.isDistinct(), ImmutableList.<Expression>of())); functions.put(symbol, new Signature("count", AGGREGATE, StandardTypes.BIGINT)); } } } return new AggregationNode( node.getId(), source, node.getGroupBy(), aggregations, functions, node.getMasks(), node.getStep(), node.getSampleWeight(), node.getConfidence(), node.getHashSymbol()); }
private static Object optimize(@Language("SQL") String expression) { assertRoundTrip(expression); Expression parsedExpression = FunctionAssertions.createExpression(expression, METADATA, SYMBOL_TYPES); IdentityHashMap<Expression, Type> expressionTypes = getExpressionTypes(TEST_SESSION, METADATA, SQL_PARSER, SYMBOL_TYPES, parsedExpression); ExpressionInterpreter interpreter = expressionOptimizer(parsedExpression, METADATA, TEST_SESSION, expressionTypes); return interpreter.optimize(new SymbolResolver() { @Override public Object getValue(Symbol symbol) { switch (symbol.getName().toLowerCase(ENGLISH)) { case "bound_long": return 1234L; case "bound_string": return utf8Slice("hello"); case "bound_double": return 12.34; case "bound_date": return new LocalDate(2001, 8, 22).toDateMidnight(DateTimeZone.UTC).getMillis(); case "bound_time": return new LocalTime(3, 4, 5, 321).toDateTime(new DateTime(0, DateTimeZone.UTC)).getMillis(); case "bound_timestamp": return new DateTime(2001, 8, 22, 3, 4, 5, 321, DateTimeZone.UTC).getMillis(); case "bound_pattern": return utf8Slice("%el%"); case "bound_timestamp_with_timezone": return new SqlTimestampWithTimeZone(new DateTime(1970, 1, 1, 1, 0, 0, 999, DateTimeZone.UTC).getMillis(), getTimeZoneKey("Z")); case "bound_varbinary": return Slices.wrappedBuffer((byte) 0xab); } return new QualifiedNameReference(symbol.toQualifiedName()); } }); }
@JsonCreator public ExchangeNode( @JsonProperty("id") PlanNodeId id, @JsonProperty("type") Type type, @JsonProperty("partitionFunction") Optional<PartitionFunctionBinding> partitionFunction, @JsonProperty("sources") List<PlanNode> sources, @JsonProperty("outputs") List<Symbol> outputs, @JsonProperty("inputs") List<List<Symbol>> inputs) { super(id); requireNonNull(type, "type is null"); requireNonNull(sources, "sources is null"); requireNonNull(partitionFunction, "partitionFunction is null"); requireNonNull(outputs, "outputs is null"); requireNonNull(inputs, "inputs is null"); if (type == Type.REPARTITION) { checkArgument(partitionFunction.isPresent(), "Repartitioning exchange must contain a partition function"); } partitionFunction .map(PartitionFunctionBinding::getPartitioningColumns) .ifPresent(list -> checkArgument(outputs.containsAll(list), "outputs must contain all partitionKeys")); partitionFunction .map(PartitionFunctionBinding::getHashColumn) .ifPresent(hashSymbol -> checkArgument(!hashSymbol.isPresent() || outputs.contains(hashSymbol.get()), "outputs must contain hashSymbol")); checkArgument(inputs.stream().allMatch(inputSymbols -> inputSymbols.size() == outputs.size()), "Input symbols do not match output symbols"); checkArgument(inputs.size() == sources.size(), "Must have same number of input lists as sources"); for (int i = 0; i < inputs.size(); i++) { checkArgument(sources.get(i).getOutputSymbols().containsAll(inputs.get(i)), "Source does not supply all required input symbols"); } this.type = type; this.sources = sources; this.partitionFunction = partitionFunction; this.outputs = ImmutableList.copyOf(outputs); this.inputs = ImmutableList.copyOf(inputs); }
public static PreferredProperties hashPartitionedWithLocal(List<Symbol> columns, List<? extends LocalProperty<Symbol>> localProperties) { return builder() .global(Global.distributed(Partitioning.hashPartitioned(columns))) .local(localProperties) .build(); }
public static PreferredProperties partitionedWithLocal(Set<Symbol> columns, List<? extends LocalProperty<Symbol>> localProperties) { return builder() .global(Global.distributed(Partitioning.partitioned(columns))) .local(localProperties) .build(); }
public static PreferredProperties undistributedWithLocal(List<? extends LocalProperty<Symbol>> localProperties) { return builder() .global(Global.undistributed()) .local(localProperties) .build(); }
public static IdentityHashMap<Expression, Type> getExpressionTypes( Session session, Metadata metadata, SqlParser sqlParser, Map<Symbol, Type> types, Iterable<? extends Expression> expressions) { return analyzeExpressionsWithSymbols(session, metadata, sqlParser, types, expressions).getExpressionTypes(); }
@Override public List<Symbol> getOutputSymbols() { if (sampleWeightSymbol.isPresent()) { return ImmutableList.<Symbol>builder().addAll(source.getOutputSymbols()).add(sampleWeightSymbol.get()).build(); } else { return source.getOutputSymbols(); } }
@Override public PlanNode visitOutput(OutputNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); List<Symbol> canonical = Lists.transform(node.getOutputSymbols(), this::canonicalize); return new OutputNode(node.getId(), source, node.getColumnNames(), canonical); }
@Override public PlanNode visitUnnest(UnnestNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); ImmutableMap.Builder<Symbol, List<Symbol>> builder = ImmutableMap.builder(); for (Map.Entry<Symbol, List<Symbol>> entry : node.getUnnestSymbols().entrySet()) { builder.put(canonicalize(entry.getKey()), entry.getValue()); } return new UnnestNode(node.getId(), source, canonicalizeAndDistinct(node.getReplicateSymbols()), builder.build(), node.getOrdinalitySymbol()); }
@Override public PlanNode optimize(PlanNode plan, Session session, Map<Symbol, Type> types, SymbolAllocator symbolAllocator, PlanNodeIdAllocator idAllocator) { requireNonNull(plan, "plan is null"); requireNonNull(session, "session is null"); requireNonNull(types, "types is null"); requireNonNull(symbolAllocator, "symbolAllocator is null"); requireNonNull(idAllocator, "idAllocator is null"); if (SystemSessionProperties.isOptimizeHashGenerationEnabled(session)) { return SimplePlanRewriter.rewriteWith(new Rewriter(idAllocator, symbolAllocator, types), plan, null); } return plan; }
@Override public PlanNode optimize(PlanNode plan, Session session, Map<Symbol, Type> types, SymbolAllocator symbolAllocator, PlanNodeIdAllocator idAllocator) { requireNonNull(plan, "plan is null"); requireNonNull(session, "session is null"); requireNonNull(types, "types is null"); requireNonNull(symbolAllocator, "symbolAllocator is null"); requireNonNull(idAllocator, "idAllocator is null"); return SimplePlanRewriter.rewriteWith(new Rewriter(metadata, sqlParser, session, types, idAllocator), plan); }
public List<Symbol> sourceOutputLayout(int sourceIndex) { // Make sure the sourceOutputLayout symbols are listed in the same order as the corresponding output symbols return getOutputSymbols().stream() .map(symbol -> symbolMapping.get(symbol).get(sourceIndex)) .collect(toImmutableList()); }
private static Map<Symbol, QualifiedNameReference> extractExchangeOutputToInput(ExchangeNode exchange, int sourceIndex) { Map<Symbol, QualifiedNameReference> outputToInputMap = new HashMap<>(); for (int i = 0; i < exchange.getOutputSymbols().size(); i++) { outputToInputMap.put(exchange.getOutputSymbols().get(i), exchange.getInputs().get(sourceIndex).get(i).toQualifiedNameReference()); } return outputToInputMap; }
@Override public List<Symbol> getOutputSymbols() { ImmutableList.Builder<Symbol> symbols = ImmutableList.builder(); symbols.addAll(groupByKeys); // output hashSymbol if present if (hashSymbol.isPresent()) { symbols.add(hashSymbol.get()); } symbols.addAll(aggregations.keySet()); return symbols.build(); }
private static OptionalInt extractUpperBound(TupleDomain<Symbol> tupleDomain, Symbol symbol) { if (tupleDomain.isNone()) { return OptionalInt.empty(); } Domain rowNumberDomain = tupleDomain.getDomains().get().get(symbol); if (rowNumberDomain == null) { return OptionalInt.empty(); } ValueSet values = rowNumberDomain.getValues(); if (values.isAll() || values.isNone() || values.getRanges().getRangeCount() <= 0) { return OptionalInt.empty(); } Range span = values.getRanges().getSpan(); if (span.getHigh().isUpperUnbounded()) { return OptionalInt.empty(); } verify(rowNumberDomain.getType().equals(BIGINT)); long upperBound = (Long) span.getHigh().getValue(); if (span.getHigh().getBound() == BELOW) { upperBound--; } if (upperBound > Integer.MAX_VALUE) { return OptionalInt.empty(); } return OptionalInt.of(Ints.checkedCast(upperBound)); }
private static boolean canOptimizeWindowFunction(WindowNode node) { if (node.getWindowFunctions().size() != 1) { return false; } Symbol rowNumberSymbol = getOnlyElement(node.getWindowFunctions().entrySet()).getKey(); return isRowNumberSignature(node.getSignatures().get(rowNumberSymbol)); }
private ListMultimap<Symbol, Symbol> canonicalizeUnionSymbolMap(ListMultimap<Symbol, Symbol> unionSymbolMap) { ImmutableListMultimap.Builder<Symbol, Symbol> builder = ImmutableListMultimap.builder(); for (Map.Entry<Symbol, Collection<Symbol>> entry : unionSymbolMap.asMap().entrySet()) { builder.putAll(canonicalize(entry.getKey()), Iterables.transform(entry.getValue(), this::canonicalize)); } return builder.build(); }
@Override public PlanNode visitTableWriter(TableWriterNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); // Intentionally does not use canonicalizeAndDistinct as that would remove columns ImmutableList<Symbol> columns = node.getColumns().stream() .map(this::canonicalize) .collect(toImmutableList()); return new TableWriterNode(node.getId(), source, node.getTarget(), columns, node.getColumnNames(), node.getOutputSymbols(), canonicalize(node.getSampleWeightSymbol())); }
@Override public PlanNode visitLimit(LimitNode node, RewriteContext<Set<Symbol>> context) { ImmutableSet.Builder<Symbol> expectedInputs = ImmutableSet.<Symbol>builder() .addAll(context.get()); PlanNode source = context.rewrite(node.getSource(), expectedInputs.build()); return new LimitNode(node.getId(), source, node.getCount()); }
@Override public ActualProperties visitSort(SortNode node, List<ActualProperties> inputProperties) { ActualProperties properties = Iterables.getOnlyElement(inputProperties); List<SortingProperty<Symbol>> localProperties = node.getOrderBy().stream() .map(column -> new SortingProperty<>(column, node.getOrderings().get(column))) .collect(toImmutableList()); return ActualProperties.builderFrom(properties) .local(localProperties) .build(); }
public static Map<Symbol, Symbol> exchangeInputToOutput(ExchangeNode node, int sourceIndex) { List<Symbol> inputSymbols = node.getInputs().get(sourceIndex); Map<Symbol, Symbol> inputToOutput = new HashMap<>(); for (int i = 0; i < node.getOutputSymbols().size(); i++) { inputToOutput.put(inputSymbols.get(i), node.getOutputSymbols().get(i)); } return inputToOutput; }
@Override public ActualProperties visitUnnest(UnnestNode node, List<ActualProperties> inputProperties) { Set<Symbol> passThroughInputs = ImmutableSet.copyOf(node.getReplicateSymbols()); return Iterables.getOnlyElement(inputProperties).translate(column -> { if (passThroughInputs.contains(column)) { return Optional.of(column); } return Optional.empty(); }); }
@Override public PlanNode visitFilter(FilterNode node, RewriteContext<Set<Symbol>> context) { Set<Symbol> expectedInputs = ImmutableSet.<Symbol>builder() .addAll(DependencyExtractor.extractUnique(node.getPredicate())) .addAll(context.get()) .build(); PlanNode source = context.rewrite(node.getSource(), expectedInputs); return new FilterNode(node.getId(), source, node.getPredicate()); }