use of org.voltdb.plannodes.HashAggregatePlanNode in project voltdb by VoltDB.
the class TestPlansGroupBy method checkMVReaggregateFeature.
// topNode, reAggNode
private void checkMVReaggregateFeature(List<AbstractPlanNode> pns, boolean needFix, int numGroupByOfTopAggNode, int numAggsOfTopAggNode, int numGroupByOfReaggNode, int numAggsOfReaggNode, boolean aggPushdown, boolean aggInline) {
assertEquals(2, pns.size());
AbstractPlanNode p = pns.get(0);
assertTrue(p instanceof SendPlanNode);
p = p.getChild(0);
if (p instanceof ProjectionPlanNode) {
p = p.getChild(0);
}
if (p instanceof LimitPlanNode) {
// No limit pushed down.
p = p.getChild(0);
}
if (p instanceof OrderByPlanNode) {
p = p.getChild(0);
}
HashAggregatePlanNode reAggNode = null;
List<AbstractPlanNode> nodes = p.findAllNodesOfClass(AbstractReceivePlanNode.class);
assertEquals(1, nodes.size());
AbstractPlanNode receiveNode = nodes.get(0);
// Indicates that there is no top aggregation node.
if (numGroupByOfTopAggNode == -1) {
if (needFix) {
p = receiveNode.getParent(0);
assertTrue(p instanceof HashAggregatePlanNode);
reAggNode = (HashAggregatePlanNode) p;
assertEquals(numGroupByOfReaggNode, reAggNode.getGroupByExpressionsSize());
assertEquals(numAggsOfReaggNode, reAggNode.getAggregateTypesSize());
p = p.getChild(0);
}
assertTrue(p instanceof ReceivePlanNode);
p = pns.get(1);
assertTrue(p instanceof SendPlanNode);
p = p.getChild(0);
assertTrue(p instanceof AbstractScanPlanNode);
return;
}
if (p instanceof ProjectionPlanNode) {
p = p.getChild(0);
}
//
// Hash top aggregate node
//
AggregatePlanNode topAggNode = null;
if (p instanceof AbstractJoinPlanNode) {
// Inline aggregation with join
topAggNode = AggregatePlanNode.getInlineAggregationNode(p);
} else {
assertTrue(p instanceof AggregatePlanNode);
topAggNode = (AggregatePlanNode) p;
p = p.getChild(0);
}
assertEquals(numGroupByOfTopAggNode, topAggNode.getGroupByExpressionsSize());
assertEquals(numAggsOfTopAggNode, topAggNode.getAggregateTypesSize());
if (needFix) {
p = receiveNode.getParent(0);
assertTrue(p instanceof HashAggregatePlanNode);
reAggNode = (HashAggregatePlanNode) p;
assertEquals(numGroupByOfReaggNode, reAggNode.getGroupByExpressionsSize());
assertEquals(numAggsOfReaggNode, reAggNode.getAggregateTypesSize());
p = p.getChild(0);
}
assertTrue(p instanceof ReceivePlanNode);
// Test the second part
p = pns.get(1);
assertTrue(p instanceof SendPlanNode);
p = p.getChild(0);
if (aggPushdown) {
assertTrue(!needFix);
if (aggInline) {
assertNotNull(AggregatePlanNode.getInlineAggregationNode(p));
} else {
assertTrue(p instanceof AggregatePlanNode);
p = p.getChild(0);
}
}
if (needFix) {
assertTrue(p instanceof AbstractScanPlanNode);
} else {
assertTrue(p instanceof AbstractScanPlanNode || p instanceof AbstractJoinPlanNode);
}
}
use of org.voltdb.plannodes.HashAggregatePlanNode in project voltdb by VoltDB.
the class TestPlansSubQueries method testPartitionedGroupByWithoutAggregate.
public void testPartitionedGroupByWithoutAggregate() {
AbstractPlanNode pn;
List<AbstractPlanNode> planNodes;
// group by non-partition column, no pushed down
planNodes = compileToFragments("SELECT * FROM (SELECT C FROM P1 GROUP BY C) T1");
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
checkSeqScan(pn, "T1");
pn = pn.getChild(0);
assertTrue(pn instanceof HashAggregatePlanNode);
pn = planNodes.get(1).getChild(0);
checkPrimaryKeyIndexScan(pn, "P1");
// count(*), no pushed down
planNodes = compileToFragments("SELECT count(*) FROM (SELECT c FROM P1 GROUP BY c) T1");
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
assertTrue(pn instanceof TableCountPlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof HashAggregatePlanNode);
pn = planNodes.get(1).getChild(0);
checkPrimaryKeyIndexScan(pn, "P1");
// group by partition column, pushed down
planNodes = compileToFragments("SELECT * FROM (SELECT A FROM P1 GROUP BY A) T1");
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
assertTrue(pn.getChild(0) instanceof ReceivePlanNode);
pn = planNodes.get(1).getChild(0);
checkSeqScan(pn, "T1");
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1");
planNodes = compileToFragments("SELECT count(*) FROM (SELECT A FROM P1 GROUP BY A) T1");
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
assertTrue(pn.getChild(0) instanceof ReceivePlanNode);
pn = planNodes.get(1).getChild(0);
assertTrue(pn instanceof TableCountPlanNode);
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1");
}
use of org.voltdb.plannodes.HashAggregatePlanNode in project voltdb by VoltDB.
the class TestPlansSubQueries method testPartitionedSameLevel.
public void testPartitionedSameLevel() {
// force it to be single partitioned.
AbstractPlanNode pn;
List<AbstractPlanNode> planNodes;
String sql, sqlNoSimplification, equivalentSql;
//
// Single partition detection : single table
//
sql = "select A FROM (SELECT A FROM P1 WHERE A = 3) T1 ";
sqlNoSimplification = "select A FROM (SELECT A FROM P1 WHERE A = 3 LIMIT 1) T1 ";
equivalentSql = "SELECT A FROM P1 T1 WHERE A = 3";
planNodes = compileToFragments(sqlNoSimplification);
assertEquals(1, planNodes.size());
pn = planNodes.get(0);
assertTrue(pn instanceof SendPlanNode);
pn = pn.getChild(0);
checkSeqScan(pn, "T1", "A");
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1", "A");
assertNotNull(((IndexScanPlanNode) pn).getInlinePlanNode(PlanNodeType.PROJECTION));
checkSubquerySimplification(sql, equivalentSql);
sql = "select A, C FROM (SELECT A, C FROM P1 WHERE A = 3) T1 ";
sqlNoSimplification = "select A, C FROM (SELECT A, C FROM P1 WHERE A = 3 LIMIT 1) T1 ";
equivalentSql = "SELECT A, C FROM P1 T1 WHERE A = 3";
planNodes = compileToFragments(sqlNoSimplification);
assertEquals(1, planNodes.size());
pn = planNodes.get(0);
assertTrue(pn instanceof SendPlanNode);
pn = pn.getChild(0);
checkSeqScan(pn, "T1", "A", "C");
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1", "A", "C");
assertNotNull(((IndexScanPlanNode) pn).getInlinePlanNode(PlanNodeType.PROJECTION));
checkSubquerySimplification(sql, equivalentSql);
// Single partition query without selecting partition column from sub-query
planNodes = compileToFragments("select C FROM (SELECT A, C FROM P1 WHERE A = 3 LIMIT 1) T1 ");
assertEquals(1, planNodes.size());
planNodes = compileToFragments("select C FROM (SELECT C FROM P1 WHERE A = 3 LIMIT 1) T1 ");
assertEquals(1, planNodes.size());
//
// AdHoc multiple partitioned sub-select queries.
//
sql = "select A1, C FROM (SELECT A A1, C FROM P1) T1 ";
sqlNoSimplification = "select A1, C FROM (SELECT DISTINCT A A1, C FROM P1) T1 ";
equivalentSql = "SELECT A A1, C FROM P1 T1";
planNodes = compileToFragments(sqlNoSimplification);
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof ReceivePlanNode);
pn = planNodes.get(1).getChild(0);
checkSeqScan(pn, "T1", "A1", "C");
checkSubquerySimplification(sql, equivalentSql);
sql = "select A1 FROM (SELECT A A1, C FROM P1 WHERE A > 3) T1 ";
sqlNoSimplification = "select A1 FROM (SELECT A A1, C FROM P1 WHERE A > 3 LIMIT 10) T1 ";
equivalentSql = "SELECT A A1 FROM P1 T1 WHERE A > 3";
planNodes = compileToFragments(sqlNoSimplification);
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
checkSeqScan(pn, "T1", "A1");
checkSubquerySimplification(sql, equivalentSql);
//
// Group by
//
planNodes = compileToFragments("select C, SD FROM " + "(SELECT C, SUM(D) as SD FROM P1 GROUP BY C) T1 ");
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
checkSeqScan(pn, "T1", "C", "SD");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
pn = pn.getChild(0);
assertTrue(pn instanceof HashAggregatePlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof ReceivePlanNode);
pn = planNodes.get(1);
assertTrue(pn instanceof SendPlanNode);
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1", "C", "SD");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
assertNotNull(pn.getInlinePlanNode(PlanNodeType.HASHAGGREGATE));
// rename group by column
planNodes = compileToFragments("select X, SD FROM " + "(SELECT C AS X, SUM(D) as SD FROM P1 GROUP BY C) T1 ");
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
checkSeqScan(pn, "T1", "X", "SD");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
pn = pn.getChild(0);
assertTrue(pn instanceof HashAggregatePlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof ReceivePlanNode);
pn = planNodes.get(1);
assertTrue(pn instanceof SendPlanNode);
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1", "C", "SD");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
assertNotNull(pn.getInlinePlanNode(PlanNodeType.HASHAGGREGATE));
AbstractPlanNode nlpn;
//
// Partitioned Joined tests
//
failToCompile("select * FROM " + "(SELECT C, SUM(D) as SD FROM P1 GROUP BY C) T1, P2 where T1.C = P2.A ", joinErrorMsg);
planNodes = compileToFragments("select T1.C, T1.SD FROM " + "(SELECT C, SUM(D) as SD FROM P1 GROUP BY C) T1, R1 Where T1.C = R1.C ");
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopPlanNode);
pn = nlpn.getChild(1);
checkSeqScan(pn, "R1");
pn = nlpn.getChild(0);
checkSeqScan(pn, "T1", "C", "SD");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
pn = pn.getChild(0);
assertTrue(pn instanceof HashAggregatePlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof ReceivePlanNode);
pn = planNodes.get(1);
assertTrue(pn instanceof SendPlanNode);
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1", "C", "SD");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
assertNotNull(pn.getInlinePlanNode(PlanNodeType.HASHAGGREGATE));
// Group by Partitioned column
planNodes = compileToFragments("select C, SD FROM " + "(SELECT A, C, SUM(D) as SD FROM P1 WHERE A > 3 GROUP BY A, C) T1 ");
assertEquals(2, planNodes.size());
planNodes = compileToFragments("select C, SD FROM " + "(SELECT A, C, SUM(D) as SD FROM P1 WHERE A = 3 GROUP BY A, C) T1 ");
assertEquals(1, planNodes.size());
planNodes = compileToFragments("select T1.C, T1.SD FROM " + "(SELECT A, C, SUM(D) as SD FROM P1 WHERE A = 3 GROUP BY A, C) T1, R1 WHERE T1.C = R1.C ");
assertEquals(1, planNodes.size());
//
// Limit
//
planNodes = compileToFragments("select C FROM (SELECT C FROM P1 WHERE A > 3 ORDER BY C LIMIT 5) T1 ");
assertEquals(2, planNodes.size());
planNodes = compileToFragments("select T1.C FROM (SELECT C FROM P1 WHERE A > 3 ORDER BY C LIMIT 5) T1, " + "R1 WHERE T1.C > R1.C ");
assertEquals(2, planNodes.size());
planNodes = compileToFragments("select C FROM (SELECT A, C FROM P1 WHERE A = 3 ORDER BY C LIMIT 5) T1 ");
assertEquals(1, planNodes.size());
// Without selecting partition column from sub-query
planNodes = compileToFragments(("select C FROM (SELECT C FROM P1 WHERE A = 3 ORDER BY C LIMIT 5) T1 "));
assertEquals(1, planNodes.size());
planNodes = compileToFragments("select T1.C FROM (SELECT A, C FROM P1 WHERE A = 3 ORDER BY C LIMIT 5) T1, " + "R1 WHERE T1.C > R1.C ");
assertEquals(1, planNodes.size());
// Without selecting partition column from sub-query
planNodes = compileToFragments("select T1.C FROM (SELECT C FROM P1 WHERE A = 3 ORDER BY C LIMIT 5) T1, " + "R1 WHERE T1.C > R1.C ");
assertEquals(1, planNodes.size());
//
// Group by & LIMIT 5
//
planNodes = compileToFragments("select C, SD FROM " + "(SELECT C, SUM(D) as SD FROM P1 GROUP BY C ORDER BY C LIMIT 5) T1 ");
assertEquals(2, planNodes.size());
// Without selecting partition column from sub-query
planNodes = compileToFragments("select C, SD FROM " + "(SELECT C, SUM(D) as SD FROM P1 WHERE A = 3 GROUP BY C ORDER BY C LIMIT 5) T1 ");
assertEquals(1, planNodes.size());
}
use of org.voltdb.plannodes.HashAggregatePlanNode in project voltdb by VoltDB.
the class MaterializedViewFixInfo method processMVBasedQueryFix.
/**
* Check whether the results from a materialized view need to be
* re-aggregated on the coordinator by the view's GROUP BY columns
* prior to any of the processing specified by the query.
* This is normally the case when a mat view's source table is partitioned
* and the view's GROUP BY does not include the partition key.
* There is a special edge case where the query already contains the exact
* reaggregations that the added-cost fix would introduce, so the fix can
* be skipped as an optimization.
* Set the m_needed flag to true, only if the reaggregation fix is needed.
* @return The value of m_needed
*/
public boolean processMVBasedQueryFix(StmtTableScan mvTableScan, Set<SchemaColumn> scanColumns, JoinNode joinTree, List<ParsedColInfo> displayColumns, List<ParsedColInfo> groupByColumns) {
//@TODO
if (!(mvTableScan instanceof StmtTargetTableScan)) {
return false;
}
Table table = ((StmtTargetTableScan) mvTableScan).getTargetTable();
assert (table != null);
String mvTableName = table.getTypeName();
Table srcTable = table.getMaterializer();
if (srcTable == null) {
return false;
}
if (table.getIsreplicated()) {
return false;
}
// Justify whether partition column is in group by column list or not
if (table.getPartitioncolumn() != null) {
return false;
}
m_mvTableScan = mvTableScan;
Set<String> mvDDLGroupbyColumnNames = new HashSet<>();
List<Column> mvColumnArray = CatalogUtil.getSortedCatalogItems(table.getColumns(), "index");
String mvTableAlias = getMVTableAlias();
// Get the number of group-by columns.
int numOfGroupByColumns;
MaterializedViewInfo mvInfo = srcTable.getViews().get(mvTableName);
if (mvInfo != null) {
// single table view
String complexGroupbyJson = mvInfo.getGroupbyexpressionsjson();
if (complexGroupbyJson.length() > 0) {
List<AbstractExpression> mvComplexGroupbyCols = null;
try {
mvComplexGroupbyCols = AbstractExpression.fromJSONArrayString(complexGroupbyJson, null);
} catch (JSONException e) {
e.printStackTrace();
}
numOfGroupByColumns = mvComplexGroupbyCols.size();
} else {
numOfGroupByColumns = mvInfo.getGroupbycols().size();
}
} else {
// joined table view
MaterializedViewHandlerInfo mvHandlerInfo = table.getMvhandlerinfo().get("mvHandlerInfo");
numOfGroupByColumns = mvHandlerInfo.getGroupbycolumncount();
}
if (scanColumns.isEmpty() && numOfGroupByColumns == 0) {
// This is an edge case that can happen if the view
// has no group by keys, and we are just
// doing a count(*) on the output of the view.
//
// Having no GB keys or scan columns would cause us to
// produce plan nodes that have a 0-column output schema.
// We can't handle this in several places, so add the
// count(*) column from the view to the scan columns.
// this is the "count(*)" column.
Column mvCol = mvColumnArray.get(0);
TupleValueExpression tve = new TupleValueExpression(mvTableName, mvTableAlias, mvCol, 0);
tve.setOrigStmtId(mvTableScan.getStatementId());
String colName = mvCol.getName();
SchemaColumn scol = new SchemaColumn(mvTableName, mvTableAlias, colName, colName, tve);
scanColumns.add(scol);
}
// Start to do real materialized view processing to fix the duplicates problem.
// (1) construct new projection columns for scan plan node.
Set<SchemaColumn> mvDDLGroupbyColumns = new HashSet<>();
NodeSchema inlineProjSchema = new NodeSchema();
for (SchemaColumn scol : scanColumns) {
inlineProjSchema.addColumn(scol);
}
for (int i = 0; i < numOfGroupByColumns; i++) {
Column mvCol = mvColumnArray.get(i);
String colName = mvCol.getName();
TupleValueExpression tve = new TupleValueExpression(mvTableName, mvTableAlias, mvCol, i);
tve.setOrigStmtId(mvTableScan.getStatementId());
mvDDLGroupbyColumnNames.add(colName);
SchemaColumn scol = new SchemaColumn(mvTableName, mvTableAlias, colName, colName, tve);
mvDDLGroupbyColumns.add(scol);
if (!scanColumns.contains(scol)) {
scanColumns.add(scol);
// construct new projection columns for scan plan node.
inlineProjSchema.addColumn(scol);
}
}
// Record the re-aggregation type for each scan columns.
Map<String, ExpressionType> mvColumnReAggType = new HashMap<>();
for (int i = numOfGroupByColumns; i < mvColumnArray.size(); i++) {
Column mvCol = mvColumnArray.get(i);
ExpressionType reAggType = ExpressionType.get(mvCol.getAggregatetype());
if (reAggType == ExpressionType.AGGREGATE_COUNT_STAR || reAggType == ExpressionType.AGGREGATE_COUNT) {
reAggType = ExpressionType.AGGREGATE_SUM;
}
mvColumnReAggType.put(mvCol.getName(), reAggType);
}
assert (inlineProjSchema.size() > 0);
m_scanInlinedProjectionNode = new ProjectionPlanNode(inlineProjSchema);
// (2) Construct the reAggregation Node.
// Construct the reAggregation plan node's aggSchema
m_reAggNode = new HashAggregatePlanNode();
int outputColumnIndex = 0;
// inlineProjSchema contains the group by columns, while aggSchema may do not.
NodeSchema aggSchema = new NodeSchema();
// Construct reAggregation node's aggregation and group by list.
for (SchemaColumn scol : inlineProjSchema.getColumns()) {
if (mvDDLGroupbyColumns.contains(scol)) {
// Add group by expression.
m_reAggNode.addGroupByExpression(scol.getExpression());
} else {
ExpressionType reAggType = mvColumnReAggType.get(scol.getColumnName());
assert (reAggType != null);
AbstractExpression agg_input_expr = scol.getExpression();
assert (agg_input_expr instanceof TupleValueExpression);
// Add aggregation information.
m_reAggNode.addAggregate(reAggType, false, outputColumnIndex, agg_input_expr);
}
aggSchema.addColumn(scol);
outputColumnIndex++;
}
assert (aggSchema.size() > 0);
m_reAggNode.setOutputSchema(aggSchema);
// Collect all TVEs that need to be do re-aggregation in coordinator.
List<TupleValueExpression> needReAggTVEs = new ArrayList<>();
List<AbstractExpression> aggPostExprs = new ArrayList<>();
for (int i = numOfGroupByColumns; i < mvColumnArray.size(); i++) {
Column mvCol = mvColumnArray.get(i);
TupleValueExpression tve = new TupleValueExpression(mvTableName, mvTableAlias, mvCol, -1);
tve.setOrigStmtId(mvTableScan.getStatementId());
needReAggTVEs.add(tve);
}
collectReAggNodePostExpressions(joinTree, needReAggTVEs, aggPostExprs);
AbstractExpression aggPostExpr = ExpressionUtil.combinePredicates(aggPostExprs);
// Add post filters for the reAggregation node.
m_reAggNode.setPostPredicate(aggPostExpr);
// ENG-5386
if (m_edgeCaseQueryNoFixNeeded && edgeCaseQueryNoFixNeeded(mvDDLGroupbyColumnNames, mvColumnReAggType, displayColumns, groupByColumns)) {
return false;
}
m_needed = true;
return true;
}
use of org.voltdb.plannodes.HashAggregatePlanNode in project voltdb by VoltDB.
the class PlanAssembler method handleMVBasedMultiPartQuery.
private AbstractPlanNode handleMVBasedMultiPartQuery(HashAggregatePlanNode reAggNode, AbstractPlanNode root, boolean edgeCaseOuterJoin) {
MaterializedViewFixInfo mvFixInfo = m_parsedSelect.m_mvFixInfo;
AbstractPlanNode receiveNode = root;
AbstractPlanNode reAggParent = null;
// re-aggregation plan node.
if (root instanceof AbstractReceivePlanNode) {
root = reAggNode;
} else {
List<AbstractPlanNode> recList = root.findAllNodesOfClass(AbstractReceivePlanNode.class);
assert (recList.size() == 1);
receiveNode = recList.get(0);
reAggParent = receiveNode.getParent(0);
boolean result = reAggParent.replaceChild(receiveNode, reAggNode);
assert (result);
}
reAggNode.addAndLinkChild(receiveNode);
reAggNode.m_isCoordinatingAggregator = true;
assert (receiveNode instanceof ReceivePlanNode);
AbstractPlanNode sendNode = receiveNode.getChild(0);
assert (sendNode instanceof SendPlanNode);
AbstractPlanNode sendNodeChild = sendNode.getChild(0);
HashAggregatePlanNode reAggNodeForReplace = null;
if (m_parsedSelect.m_tableList.size() > 1 && !edgeCaseOuterJoin) {
reAggNodeForReplace = reAggNode;
}
boolean find = mvFixInfo.processScanNodeWithReAggNode(sendNode, reAggNodeForReplace);
assert (find);
// receive node with materialized view scan node.
if (m_parsedSelect.m_tableList.size() > 1 && !edgeCaseOuterJoin) {
AbstractPlanNode joinNode = sendNodeChild;
// No agg, limit pushed down at this point.
assert (joinNode instanceof AbstractJoinPlanNode);
// Fix the node after Re-aggregation node.
joinNode.clearParents();
assert (mvFixInfo.m_scanNode != null);
mvFixInfo.m_scanNode.clearParents();
// replace joinNode with MV scan node on each partition.
sendNode.clearChildren();
sendNode.addAndLinkChild(mvFixInfo.m_scanNode);
// its parent will be the parent of the new join node. Update the root node.
if (reAggParent != null) {
reAggParent.replaceChild(reAggNode, joinNode);
root = reAggParent;
} else {
root = joinNode;
}
}
return root;
}
Aggregations