test_class.file: parser/src/test/java/com/qihoo/qsql/org/apache/calcite/materialize/LatticeSuggesterTest.java
test_class.identifier: LatticeSuggesterTest
test_case.body: @Test public void testExpression() throws Exception {
      final Tester t = new Tester().foodmart().withEvolve(true);
  
      final String q0 = "select\n"
          + "  \"fname\" || ' ' || \"lname\" as \"full_name\",\n"
          + "  count(*) as c,\n"
          + "  avg(\"total_children\" - \"num_children_at_home\")\n"
          + "from \"customer\"\n"
          + "group by \"fname\", \"lname\"";
      final String l0 = "customer:[COUNT(), AVG($f2)]";
      t.addQuery(q0);
      assertThat(t.s.latticeMap.size(), is(1));
      assertThat(Iterables.getOnlyElement(t.s.latticeMap.keySet()),
          is(l0));
      final Lattice lattice = Iterables.getOnlyElement(t.s.latticeMap.values());
      final List<Lattice.DerivedColumn> derivedColumns = lattice.columns.stream()
          .filter(c -> c instanceof Lattice.DerivedColumn)
          .map(c -> (Lattice.DerivedColumn) c)
          .collect(Collectors.toList());
      assertThat(derivedColumns.size(), is(2));
      final List<String> tables = ImmutableList.of("customer");
      checkDerivedColumn(lattice, tables, derivedColumns, 0, "$f2", true);
      checkDerivedColumn(lattice, tables, derivedColumns, 1, "full_name", false);
    }
test_case.class_method_signature: LatticeSuggesterTest.testExpression()
test_case.full_signature: @Test public void testExpression()
test_case.identifier: testExpression
test_case.invocations: withEvolve foodmart addQuery assertThat size is assertThat getOnlyElement keySet is getOnlyElement values collect map filter stream toList assertThat size is of checkDerivedColumn checkDerivedColumn
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void testExpression()
focal_class.declarator: space
focal_class.modifier: final
focal_class.original_string: final LatticeSpace space;
focal_class.type: LatticeSpace
focal_class.var_name: space
focal_class.declarator: PROGRAM =
        new HepProgramBuilder()
            .addRuleInstance(FilterJoinRule.FILTER_ON_JOIN)
            .addRuleInstance(FilterJoinRule.JOIN)
            .build()
focal_class.modifier: private static final
focal_class.original_string: private static final HepProgram PROGRAM =
        new HepProgramBuilder()
            .addRuleInstance(FilterJoinRule.FILTER_ON_JOIN)
            .addRuleInstance(FilterJoinRule.JOIN)
            .build();
focal_class.type: HepProgram
focal_class.var_name: PROGRAM
focal_class.declarator: latticeMap = new LinkedHashMap<>()
focal_class.modifier: final
focal_class.original_string: final Map<String, Lattice> latticeMap = new LinkedHashMap<>();
focal_class.type: Map<String, Lattice>
focal_class.var_name: latticeMap
focal_class.declarator: obsoleteLatticeMap = new HashMap<>()
focal_class.modifier: private final
focal_class.original_string: private final Map<Lattice, Lattice> obsoleteLatticeMap = new HashMap<>();
focal_class.type: Map<Lattice, Lattice>
focal_class.var_name: obsoleteLatticeMap
focal_class.declarator: evolve
focal_class.modifier: private final
focal_class.original_string: private final boolean evolve;
focal_class.type: boolean
focal_class.var_name: evolve
focal_class.file: parser/src/main/java/com/qihoo/qsql/org/apache/calcite/materialize/LatticeSuggester.java
focal_class.identifier: LatticeSuggester
focal_class.class_method_signature: LatticeSuggester.LatticeSuggester(FrameworkConfig config)
focal_class.full_signature: public  LatticeSuggester(FrameworkConfig config)
focal_class.identifier: LatticeSuggester
focal_class.modifiers: public
focal_class.parameters: (FrameworkConfig config)
focal_class.signature:  LatticeSuggester(FrameworkConfig config)
focal_class.class_method_signature: LatticeSuggester.getLatticeSet()
focal_class.full_signature: public Set<Lattice> getLatticeSet()
focal_class.identifier: getLatticeSet
focal_class.modifiers: public
focal_class.parameters: ()
focal_class.return: Set<Lattice>
focal_class.signature: Set<Lattice> getLatticeSet()
focal_class.class_method_signature: LatticeSuggester.addQuery(RelNode r)
focal_class.full_signature: public List<Lattice> addQuery(RelNode r)
focal_class.identifier: addQuery
focal_class.modifiers: public
focal_class.parameters: (RelNode r)
focal_class.return: List<Lattice>
focal_class.signature: List<Lattice> addQuery(RelNode r)
focal_class.class_method_signature: LatticeSuggester.deriveAlias(MutableMeasure measure,
        DerivedColRef derivedColRef)
focal_class.full_signature: private static String deriveAlias(MutableMeasure measure,
        DerivedColRef derivedColRef)
focal_class.identifier: deriveAlias
focal_class.modifiers: private static
focal_class.parameters: (MutableMeasure measure,
        DerivedColRef derivedColRef)
focal_class.return: String
focal_class.signature: String deriveAlias(MutableMeasure measure,
        DerivedColRef derivedColRef)
focal_class.class_method_signature: LatticeSuggester.findMatch(final Lattice lattice, MutableNode mutableNode)
focal_class.full_signature: private Lattice findMatch(final Lattice lattice, MutableNode mutableNode)
focal_class.identifier: findMatch
focal_class.modifiers: private
focal_class.parameters: (final Lattice lattice, MutableNode mutableNode)
focal_class.return: Lattice
focal_class.signature: Lattice findMatch(final Lattice lattice, MutableNode mutableNode)
focal_class.class_method_signature: LatticeSuggester.copyMeasures(Lattice.Builder builder, Lattice lattice)
focal_class.full_signature: private void copyMeasures(Lattice.Builder builder, Lattice lattice)
focal_class.identifier: copyMeasures
focal_class.modifiers: private
focal_class.parameters: (Lattice.Builder builder, Lattice lattice)
focal_class.return: void
focal_class.signature: void copyMeasures(Lattice.Builder builder, Lattice lattice)
focal_class.class_method_signature: LatticeSuggester.matchQuality(Lattice lattice, Lattice target)
focal_class.full_signature: private int matchQuality(Lattice lattice, Lattice target)
focal_class.identifier: matchQuality
focal_class.modifiers: private
focal_class.parameters: (Lattice lattice, Lattice target)
focal_class.return: int
focal_class.signature: int matchQuality(Lattice lattice, Lattice target)
focal_class.class_method_signature: LatticeSuggester.minus(Collection<E> c, Collection<E> c2)
focal_class.full_signature: private static Set<E> minus(Collection<E> c, Collection<E> c2)
focal_class.identifier: minus
focal_class.modifiers: private static
focal_class.parameters: (Collection<E> c, Collection<E> c2)
focal_class.return: Set<E>
focal_class.signature: Set<E> minus(Collection<E> c, Collection<E> c2)
focal_class.class_method_signature: LatticeSuggester.frame(final Query q, RelNode r)
focal_class.full_signature: private Frame frame(final Query q, RelNode r)
focal_class.identifier: frame
focal_class.modifiers: private
focal_class.parameters: (final Query q, RelNode r)
focal_class.return: Frame
focal_class.signature: Frame frame(final Query q, RelNode r)
focal_method.body: public List<Lattice> addQuery(RelNode r) {
      // Push filters into joins and towards leaves
      final HepPlanner planner =
          new HepPlanner(PROGRAM, null, true, null, RelOptCostImpl.FACTORY);
      planner.setRoot(r);
      final RelNode r2 = planner.findBestExp();
  
      final Query q = new Query(space);
      final Frame frame = frame(q, r2);
      if (frame == null) {
        return ImmutableList.of();
      }
      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.t, hop.target.t),
            IntPair.of(hop.source.c, hop.target.c));
      }
      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 ImmutableList.of();
      }
  
      // Translate the query graph to mutable nodes
      final Map<TableRef, 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 =
              ImmutableList.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());
            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
      final List<Lattice> lattices = new ArrayList<>();
      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 ImmutableList.of();
            }
          }
          latticeBuilder.addMeasure(
              new Lattice.Measure(measure.aggregate, measure.distinct,
                  measure.name,
                  Lists.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);
      }
      return ImmutableList.copyOf(lattices);
    }
focal_method.class_method_signature: LatticeSuggester.addQuery(RelNode r)
focal_method.full_signature: public List<Lattice> addQuery(RelNode r)
focal_method.identifier: addQuery
focal_method.invocations: setRoot findBestExp frame of create create addVertex put of of entrySet asMap getKey getKey stepRef copyOf getValue addVertex source addVertex target addEdge source target findCycles isEmpty of of getInwardEdges size add get get source of get put get source add put isCyclic createRootSchema flatten of addMeasure transform get indexOf column deriveAlias expression tableAliases use column expression tableAliases use build findMatch add copyOf
focal_method.modifiers: public
focal_method.parameters: (RelNode r)
focal_method.return: List<Lattice>
focal_method.signature: List<Lattice> addQuery(RelNode r)