private void addFrame()

in core/src/main/java/org/apache/calcite/materialize/LatticeSuggester.java [149:279]


  private void addFrame(Query q, Frame frame, List<Lattice> lattices) {
    final AttributedDirectedGraph<TableRef, StepRef> g =
        AttributedDirectedGraph.create(new StepRef.Factory());
    final Multimap<Pair<TableRef, TableRef>, IntPair> map =
        LinkedListMultimap.create();
    for (TableRef tableRef : frame.tableRefs) {
      g.addVertex(tableRef);
    }
    for (Hop hop : frame.hops) {
      map.put(Pair.of(hop.source.tableRef(), hop.target.tableRef()),
          IntPair.of(hop.source.col(space), hop.target.col(space)));
    }
    for (Map.Entry<Pair<TableRef, TableRef>, Collection<IntPair>> e
        : map.asMap().entrySet()) {
      final TableRef source = e.getKey().left;
      final TableRef target = e.getKey().right;
      final StepRef stepRef =
          q.stepRef(source, target, ImmutableList.copyOf(e.getValue()));
      g.addVertex(stepRef.source());
      g.addVertex(stepRef.target());
      g.addEdge(stepRef.source(), stepRef.target(), stepRef.step,
          stepRef.ordinalInQuery);
    }

    // If the join graph is cyclic, we can't use it.
    final Set<TableRef> cycles = new CycleDetector<>(g).findCycles();
    if (!cycles.isEmpty()) {
      return;
    }

    // Translate the query graph to mutable nodes
    final IdentityHashMap<TableRef, @Nullable MutableNode> nodes = new IdentityHashMap<>();
    final Map<List, MutableNode> nodesByParent = new HashMap<>();
    final List<MutableNode> rootNodes = new ArrayList<>();
    for (TableRef tableRef : TopologicalOrderIterator.of(g)) {
      final List<StepRef> edges = g.getInwardEdges(tableRef);
      final MutableNode node;
      switch (edges.size()) {
      case 0:
        node = new MutableNode(tableRef.table);
        rootNodes.add(node);
        break;
      case 1:
        final StepRef edge = edges.get(0);
        final MutableNode parent = nodes.get(edge.source());
        final List key =
            FlatLists.of(parent, tableRef.table, edge.step.keys);
        final MutableNode existingNode = nodesByParent.get(key);
        if (existingNode == null) {
          node = new MutableNode(tableRef.table, parent, edge.step);
          nodesByParent.put(key, node);
        } else {
          node = existingNode;
        }
        break;
      default:
        for (StepRef edge2 : edges) {
          final MutableNode parent2 = nodes.get(edge2.source());
          requireNonNull(
              parent2,
              () -> "parent for " + edge2.source());
          final MutableNode node2 =
              new MutableNode(tableRef.table, parent2, edge2.step);
          parent2.children.add(node2);
        }
        node = null;
        break;
      }
      nodes.put(tableRef, node);
    }

    // Transcribe the hierarchy of mutable nodes to immutable nodes
    for (MutableNode rootNode : rootNodes) {
      if (rootNode.isCyclic()) {
        continue;
      }
      final CalciteSchema rootSchema = CalciteSchema.createRootSchema(false);
      final Lattice.Builder latticeBuilder =
          new Lattice.Builder(space, rootSchema, rootNode);

      final List<MutableNode> flatNodes = new ArrayList<>();
      rootNode.flatten(flatNodes);

      for (MutableMeasure measure : frame.measures) {
        for (ColRef arg : measure.arguments) {
          if (arg == null) {
            // Cannot handle expressions, e.g. "sum(x + 1)" yet
            return;
          }
        }
        latticeBuilder.addMeasure(
            new Lattice.Measure(measure.aggregate, measure.distinct,
                measure.name,
                Util.transform(measure.arguments, colRef -> {
                  final Lattice.Column column;
                  if (colRef instanceof BaseColRef) {
                    final BaseColRef baseColRef = (BaseColRef) colRef;
                    final MutableNode node = nodes.get(baseColRef.t);
                    final int table = flatNodes.indexOf(node);
                    column = latticeBuilder.column(table, baseColRef.c);
                  } else if (colRef instanceof DerivedColRef) {
                    final DerivedColRef derivedColRef =
                        (DerivedColRef) colRef;
                    final String alias = deriveAlias(measure, derivedColRef);
                    column =
                        latticeBuilder.expression(derivedColRef.e, alias,
                            derivedColRef.tableAliases());
                  } else {
                    throw new AssertionError("expression in measure");
                  }
                  latticeBuilder.use(column, true);
                  return column;
                })));
      }

      for (int i = 0; i < frame.columnCount; i++) {
        final ColRef c = frame.column(i);
        if (c instanceof DerivedColRef) {
          final DerivedColRef derivedColRef = (DerivedColRef) c;
          final Lattice.Column expression =
              latticeBuilder.expression(derivedColRef.e,
                  derivedColRef.alias, derivedColRef.tableAliases());
          latticeBuilder.use(expression, false);
        }
      }

      final Lattice lattice0 = latticeBuilder.build();
      final Lattice lattice1 = findMatch(lattice0, rootNode);
      lattices.add(lattice1);
    }
  }