protected SelectStatement buildAggCommand(SelectStatement in) {
    SelectStatement out = CopyVisitor.copy(in);
    // we're going to build
    // select Name, max(Engine), max(Version), max(Row_format),
    // sum(Rows), avg(Avg_row_length), sum(Data_length),
    // max(Max_data_length), sum(Index_length),
    // sum(Data_free), max(Auto_increment), min(Create_time),
    // max(Update_time), max(Check_time),
    // max(Collation), null /*Checksum*/, max(Create_options), max(Comment) from temp1 group by Name

    // eventually we will build another temp table of rewrite info (visible name, auto_inc values)
    // and join
    // but for now this is good enough

    List<ExpressionNode> proj = new ArrayList<ExpressionNode>();
    ExpressionAlias nameColumn = null;
    for (ExpressionNode en : out.getProjection()) {
      ExpressionAlias ea = (ExpressionAlias) en;
      ColumnInstance ci = (ColumnInstance) ea.getTarget();
      String cn = ci.getColumn().getName().getUnquotedName().get();
      FunctionCall fc = null;
      if (maxedColumns.contains(cn)) {
        fc = new FunctionCall(FunctionName.makeMax(), ci);
      } else if (summedColumns.contains(cn)) {
        fc = new FunctionCall(FunctionName.makeSum(), ci);
      } else if ("Name".equals(cn)) {
        fc = null;
        nameColumn = ea;
      } else if ("Avg_row_length".equals(cn)) {
        fc =
            new FunctionCall(
                FunctionName.makeRound(), new FunctionCall(FunctionName.makeAvg(), ci));
      } else if ("Create_time".equals(cn)) {
        fc = new FunctionCall(FunctionName.makeMin(), ci);
      } else if ("Checksum".equals(cn)) {
        fc = null;
        ea =
            new ExpressionAlias(
                LiteralExpression.makeNullLiteral(),
                new NameAlias(ci.getColumn().getName().getUnqualified()),
                false);
      } else {
        throw new SchemaException(Pass.PLANNER, "Unknown show status column: " + cn);
      }
      if (fc != null) {
        ea =
            new ExpressionAlias(
                fc, new NameAlias(ci.getColumn().getName().getUnqualified()), false);
      }
      proj.add(ea);
    }
    out.setProjection(proj);
    SortingSpecification ngb = new SortingSpecification(nameColumn.buildAliasInstance(), true);
    ngb.setOrdering(Boolean.FALSE);
    out.getGroupBysEdge().add(ngb);

    return out;
  }
 @Override
 public void plan(SchemaContext pc, ExecutionSequence es, BehaviorConfiguration config)
     throws PEException {
   Database<?> ondb = null;
   for (TableKey tk : tables) {
     if (ondb == null) ondb = tk.getTable().getDatabase(pc);
     else if (!ondb.equals(tk.getTable().getDatabase(pc)))
       throw new SchemaException(Pass.PLANNER, "Unable to show table status across databases");
   }
   String origCommand = buildInitialShowStatusCommand();
   if (onGroup.isSingleSiteGroup()) {
     es.append(ProjectingExecutionStep.build(pc, ondb, onGroup, origCommand));
   } else {
     //		System.out.println(origCommand);
     TempGroupManager tgm = new TempGroupManager();
     TempTable t1 = buildFirstTempTable(pc, tgm.getGroup(true));
     if (!pc.hasCurrentDatabase() && !t1.hasDatabase(pc)) {
       // if no current database is set and the temp table has no database
       // we need to set one
       t1.setDatabase(pc, (PEDatabase) ondb, false);
     }
     SelectStatement firstSelect = buildFirstSelect(pc, t1);
     DistributionKeyTemplate dkt = buildKeyTemplate();
     for (int i = 0; i < firstSelect.getProjectionEdge().size(); i++)
       dkt.addColumn(firstSelect.getProjectionEdge().get(i), i);
     DistributionVector sourceVect = buildVector(pc);
     tgm.plan(pc);
     es.append(
         RedistributionExecutionStep.build(
             pc, ondb, onGroup, origCommand, sourceVect, t1, t1.getStorageGroup(pc), dkt, null));
     SelectStatement aggCommand = buildAggCommand(firstSelect);
     //		System.out.println(aggCommand.getSQL());
     es.append(
         ProjectingExecutionStep.build(
             pc, ondb, t1.getStorageGroup(pc), null, null, aggCommand, null));
   }
 }
 public static SelectStatement filterEntryProjection(SelectStatement in, PartitionEntry jre)
     throws PEException {
   PartitionEntry actual = jre.getActualEntry();
   SelectStatement expecting = null;
   if (actual instanceof OriginalPartitionEntry)
     expecting = ((OriginalPartitionEntry) actual).getChildCopy();
   else expecting = actual.getJoinQuery(null);
   ListSet<ColumnKey> ec = new ListSet<ColumnKey>();
   for (ExpressionNode en : expecting.getProjection()) {
     ExpressionNode targ = ExpressionUtils.getTarget(en);
     if (targ instanceof ColumnInstance) {
       ColumnKey was = ((ColumnInstance) targ).getColumnKey();
       ColumnKey isnow = in.getMapper().copyColumnKeyForward(was);
       if (isnow == null) {
         throw new SchemaException(Pass.PLANNER, "Lost column during lookup table join");
       }
       ec.add(isnow);
     } else if (targ instanceof FunctionCall) {
       ExpressionNode exn = targ;
       RewriteKey rk = in.getMapper().mapExpressionToColumn(exn);
       while (rk == null && (exn.getParent() instanceof ExpressionNode)) {
         exn = (ExpressionNode) exn.getParent();
         rk = in.getMapper().mapExpressionToColumn(exn);
       }
       if (rk != null) {
         ec.add((ColumnKey) rk);
       }
     }
   }
   for (Iterator<ExpressionNode> iter = in.getProjectionEdge().iterator(); iter.hasNext(); ) {
     ExpressionNode en = ExpressionUtils.getTarget(iter.next());
     if (en instanceof ColumnInstance) {
       ColumnKey ck = ((ColumnInstance) en).getColumnKey();
       if (!ec.contains(ck)) iter.remove();
     }
   }
   return in;
 }
  public static RedistFeatureStep buildLookupJoinRedist(
      PlannerContext pc,
      RedistFeatureStep lookupTable,
      List<ExpressionNode> lookupJoinColumns,
      PEStorageGroup targetGroup,
      JoinEntry origEntry,
      List<ExpressionNode> origJoinColumns,
      PartitionEntry nonLookupSide)
      throws PEException {
    // we will modify the existing non lookup side projecting feature step, and add the lookup table
    // as a requirement to it.
    ProjectingFeatureStep nonLookupStep = (ProjectingFeatureStep) nonLookupSide.getStep(null);
    nonLookupSide.maybeForceDoublePrecision(nonLookupStep);
    SelectStatement lookupSelect = lookupTable.getTargetTempTable().buildSelect(pc.getContext());
    SelectStatement nonLookupSelect = (SelectStatement) nonLookupStep.getPlannedStatement();

    SelectStatement actualJoinStatement =
        DMLStatementUtils.compose(pc.getContext(), nonLookupSelect, lookupSelect);
    List<ExpressionNode> ands =
        ExpressionUtils.decomposeAndClause(actualJoinStatement.getWhereClause());

    // instead of building the join spec directly, map forward the original join condition from the
    // joined table if it's available
    IndexCollector ic = new IndexCollector();
    if (origEntry.getJoin().getJoin() != null) {
      FunctionCall mapped =
          (FunctionCall)
              actualJoinStatement
                  .getMapper()
                  .copyForward(origEntry.getJoin().getJoin().getJoinOn());
      ands.add(mapped);
      ListSet<ColumnInstance> cols = ColumnInstanceCollector.getColumnInstances(mapped);
      for (ColumnInstance ci : cols) ic.addColumnInstance(ci);
    } else {
      Map<RewriteKey, ExpressionNode> projEntries = null;
      for (int i = 0; i < origJoinColumns.size(); i++) {
        ColumnKey mck =
            actualJoinStatement.getMapper().mapExpressionToColumn(origJoinColumns.get(i));
        ColumnKey muck =
            actualJoinStatement.getMapper().mapExpressionToColumn(lookupJoinColumns.get(i));
        ExpressionNode mc = null;
        ExpressionNode muc = null;
        if (mck == null || muck == null) {
          if (projEntries == null) {
            projEntries = new HashMap<RewriteKey, ExpressionNode>();
            for (ExpressionNode en : actualJoinStatement.getProjectionEdge()) {
              ExpressionNode actual = ExpressionUtils.getTarget(en);
              if (actual instanceof ColumnInstance) {
                projEntries.put(((ColumnInstance) actual).getColumnKey(), actual);
              } else {
                projEntries.put(new ExpressionKey(actual), actual);
              }
            }
          }
          if (mck == null)
            mc =
                (ExpressionNode)
                    projEntries.get(new ExpressionKey(origJoinColumns.get(i))).copy(null);
          if (muck == null)
            mc =
                (ExpressionNode)
                    projEntries.get(new ExpressionKey(lookupJoinColumns.get(i))).copy(null);
        }
        if (mc == null) mc = mck.toInstance();
        if (muc == null) muc = muck.toInstance();
        if (mc instanceof ColumnInstance) ic.addColumnInstance((ColumnInstance) mc);
        if (muc instanceof ColumnInstance) ic.addColumnInstance((ColumnInstance) muc);
        FunctionCall eq = new FunctionCall(FunctionName.makeEquals(), mc, muc);
        ands.add(eq);
      }
    }
    ic.setIndexes(origEntry.getSchemaContext());

    TempTable lookupEntryTarget = lookupTable.getTargetTempTable();

    // everything from the lhs that's in the projection should be cleared - it's invisible
    // note that we do it after building the where clause so that the original join condition can be
    // mapped
    for (Iterator<ExpressionNode> iter = actualJoinStatement.getProjectionEdge().iterator();
        iter.hasNext(); ) {
      ExpressionNode en = iter.next();
      ExpressionNode targ = ExpressionUtils.getTarget(en);
      if (targ instanceof ColumnInstance) {
        ColumnInstance ci = (ColumnInstance) targ;
        if (ci.getTableInstance().getAbstractTable() == lookupEntryTarget) iter.remove();
      }
    }

    actualJoinStatement.setWhereClause(ExpressionUtils.safeBuildAnd(ands));
    actualJoinStatement.normalize(origEntry.getSchemaContext());

    // build a new projecting feature step
    ProjectingFeatureStep lookupJoinStep =
        DefaultFeatureStepBuilder.INSTANCE.buildProjectingStep(
            origEntry.getPlannerContext(),
            origEntry.getFeaturePlanner(),
            actualJoinStatement,
            new ExecutionCost(false, false, null, -1),
            nonLookupStep.getSourceGroup(),
            actualJoinStatement.getDatabase(origEntry.getSchemaContext()),
            nonLookupStep.getDistributionVector(),
            null,
            DMLExplainReason.LOOKUP_JOIN.makeRecord());

    // arrange for the children of the nonlookup side to become my children
    // and add the lookup table step as well
    lookupJoinStep.getSelfChildren().addAll(nonLookupStep.getAllChildren());
    lookupJoinStep.getSelfChildren().add(lookupTable);
    // children must be sequential - no need to modify here

    List<Integer> mappedRedistOn =
        nonLookupSide.mapDistributedOn(origJoinColumns, actualJoinStatement);

    // now remove the lookup table from the mapper - have to do this pretty late - at this point
    // the query won't be manipulated any more
    actualJoinStatement.getMapper().remove(lookupEntryTarget);

    RedistFeatureStep out =
        lookupJoinStep.redist(
            origEntry.getPlannerContext(),
            origEntry.getFeaturePlanner(),
            new TempTableCreateOptions(Model.STATIC, targetGroup)
                .distributeOn(mappedRedistOn)
                .withRowCount(origEntry.getScore().getRowCount()),
            null,
            DMLExplainReason.LOOKUP_JOIN.makeRecord());
    return out;
  }
  // we have the temp table on the temp group for the constrained side
  // we need to build the bcast temp table on the pers group
  public static RedistFeatureStep buildLookupTableRedist(
      PlannerContext pc,
      PartitionEntry srcEntry,
      RedistFeatureStep constrainedOnTempGroup,
      JoinEntry rje,
      PEStorageGroup targetGroup,
      boolean indexJoinColumns)
      throws PEException {
    ProjectingFeatureStep selectDistinct =
        constrainedOnTempGroup.buildNewProjectingStep(
            pc,
            rje.getFeaturePlanner(),
            null,
            DMLExplainReason.LOOKUP_JOIN_LOOKUP_TABLE.makeRecord());
    SelectStatement ss = (SelectStatement) selectDistinct.getPlannedStatement();
    DistributionVector distVect =
        constrainedOnTempGroup.getTargetTempTable().getDistributionVector(pc.getContext());

    ListSet<ColumnKey> mappedColumnsInJoin = null;
    if (rje.getJoin().getJoin() != null) {
      ListSet<ColumnKey> columnsInJoin =
          ColumnInstanceCollector.getColumnKeys(
              ColumnInstanceCollector.getColumnInstances(rje.getJoin().getJoin().getJoinOn()));
      // build the set of columns in the src entry projection
      ListSet<ColumnKey> srcColumns = new ListSet<ColumnKey>();
      for (BufferEntry be : srcEntry.getBufferEntries()) {
        ExpressionNode targ = ExpressionUtils.getTarget(be.getTarget());
        if (targ instanceof ColumnInstance) {
          ColumnInstance ci = (ColumnInstance) targ;
          srcColumns.add(ci.getColumnKey());
        }
      }
      columnsInJoin.retainAll(srcColumns);
      mappedColumnsInJoin = new ListSet<ColumnKey>();
      for (ColumnKey ck : columnsInJoin) {
        mappedColumnsInJoin.add(ss.getMapper().copyColumnKeyForward(ck));
      }
    }

    for (Iterator<ExpressionNode> iter = ss.getProjectionEdge().iterator(); iter.hasNext(); ) {
      ExpressionNode en = iter.next();
      if (en instanceof ColumnInstance) {
        ColumnInstance ci = (ColumnInstance) en;
        PEColumn pec = ci.getPEColumn();
        if (!distVect.contains(srcEntry.getSchemaContext(), pec)
            && (mappedColumnsInJoin == null || !mappedColumnsInJoin.contains(ci.getColumnKey())))
          iter.remove();
      }
    }
    ss.setSetQuantifier(SetQuantifier.DISTINCT);
    ss.normalize(srcEntry.getSchemaContext());

    // now that we have the select distinct set up
    // redistribute it bcast back onto the pers group
    RedistFeatureStep out =
        selectDistinct.redist(
            pc,
            rje.getFeaturePlanner(),
            new TempTableCreateOptions(Model.BROADCAST, targetGroup),
            null,
            DMLExplainReason.LOOKUP_JOIN_LOOKUP_TABLE.makeRecord());

    if (indexJoinColumns)
      out.getTargetTempTable()
          .noteJoinedColumns(pc.getContext(), out.getTargetTempTable().getColumns(pc.getContext()));

    return out;
  }