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; }