예제 #1
0
  private RelationPlan planCrossJoinUnnest(RelationPlan leftPlan, Join joinNode, Unnest node) {
    TupleDescriptor outputDescriptor = analysis.getOutputDescriptor(joinNode);
    TupleDescriptor unnestOutputDescriptor = analysis.getOutputDescriptor(node);
    // Create symbols for the result of unnesting
    ImmutableList.Builder<Symbol> unnestedSymbolsBuilder = ImmutableList.builder();
    for (Field field : unnestOutputDescriptor.getVisibleFields()) {
      Symbol symbol = symbolAllocator.newSymbol(field);
      unnestedSymbolsBuilder.add(symbol);
    }
    ImmutableList<Symbol> unnestedSymbols = unnestedSymbolsBuilder.build();

    // Add a projection for all the unnest arguments
    PlanBuilder planBuilder = initializePlanBuilder(leftPlan);
    planBuilder = appendProjections(planBuilder, node.getExpressions());
    TranslationMap translations = planBuilder.getTranslations();
    ProjectNode projectNode =
        checkType(planBuilder.getRoot(), ProjectNode.class, "planBuilder.getRoot()");

    ImmutableMap.Builder<Symbol, List<Symbol>> unnestSymbols = ImmutableMap.builder();
    UnmodifiableIterator<Symbol> unnestedSymbolsIterator = unnestedSymbols.iterator();
    for (Expression expression : node.getExpressions()) {
      Type type = analysis.getType(expression);
      Symbol inputSymbol = translations.get(expression);
      if (type instanceof ArrayType) {
        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");

    UnnestNode unnestNode =
        new UnnestNode(
            idAllocator.getNextId(),
            projectNode,
            leftPlan.getOutputSymbols(),
            unnestSymbols.build(),
            ordinalitySymbol);
    return new RelationPlan(
        unnestNode, outputDescriptor, unnestNode.getOutputSymbols(), Optional.empty());
  }
예제 #2
0
 @Override
 public Void visitUnnest(UnnestNode node, Void context) {
   if (node.getOrdinalitySymbol() == null) {
     printNode(
         node,
         format("Unnest[%s]", node.getUnnestSymbols().keySet()),
         NODE_COLORS.get(NodeType.UNNEST));
   } else {
     printNode(
         node,
         format("Unnest[%s (ordinality)]", node.getUnnestSymbols().keySet()),
         NODE_COLORS.get(NodeType.UNNEST));
   }
   return node.getSource().accept(this, context);
 }
예제 #3
0
    @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);
    }
예제 #4
0
    @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();
              });
    }