use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class TestPlansSubQueries method testUnions.
public void testUnions() {
AbstractPlanNode pn;
pn = compile("select A, C FROM (SELECT A, C FROM R1 UNION SELECT A, C FROM R2 UNION SELECT A, C FROM R3) T1 order by A ");
pn = pn.getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof OrderByPlanNode);
pn = pn.getChild(0);
checkSeqScan(pn, "T1", "A", "C");
AbstractPlanNode upn = pn.getChild(0);
assertTrue(upn instanceof UnionPlanNode);
pn = upn.getChild(0);
checkSeqScan(pn, "R1", "A", "C");
pn = upn.getChild(1);
checkSeqScan(pn, "R2", "A", "C");
pn = upn.getChild(2);
checkSeqScan(pn, "R3", "A", "C");
String message = "This query is not plannable. It has a subquery which needs cross-partition access.";
failToCompile("select * FROM " + "(SELECT A, COUNT(*) FROM P1 GROUP BY A " + "UNION " + "SELECT A, COUNT(*) FROM R2 GROUP BY A) T1 , P2 where T1.A = P2.A ", message);
}
use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class TestUnion method checkOrderByNode.
private void checkOrderByNode(AbstractPlanNode pn, String[] columns, int[] idxs) {
assertTrue(pn != null);
assertTrue(pn instanceof OrderByPlanNode);
OrderByPlanNode opn = (OrderByPlanNode) pn;
assertEquals(columns.length, opn.getOutputSchema().size());
for (int i = 0; i < columns.length; ++i) {
SchemaColumn col = opn.getOutputSchema().getColumns().get(i);
assertEquals(columns[i], col.getColumnAlias());
AbstractExpression colExpr = col.getExpression();
assertEquals(ExpressionType.VALUE_TUPLE, colExpr.getExpressionType());
assertEquals(idxs[i], ((TupleValueExpression) colExpr).getColumnIndex());
}
}
use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class TestPlansDistinct method checkDistinctWithGroupbyPlans.
/**
*
* @param distinctSQL Group by query with distinct
* @param groupbySQL Group by query without distinct
*/
protected void checkDistinctWithGroupbyPlans(String distinctSQL, String groupbySQL, boolean limitPushdown) {
List<AbstractPlanNode> pns1 = compileToFragments(distinctSQL);
List<AbstractPlanNode> pns2 = compileToFragments(groupbySQL);
//printExplainPlan(pns1);
//printExplainPlan(pns2);
assertTrue(pns1.get(0) instanceof SendPlanNode);
assertTrue(pns2.get(0) instanceof SendPlanNode);
AbstractPlanNode apn1, apn2;
apn1 = pns1.get(0).getChild(0);
apn2 = pns2.get(0).getChild(0);
boolean hasTopProjection1 = false;
if (apn1 instanceof ProjectionPlanNode) {
apn1 = apn1.getChild(0);
hasTopProjection1 = true;
}
boolean hasTopProjection2 = false;
if (apn2 instanceof ProjectionPlanNode) {
apn2 = apn2.getChild(0);
hasTopProjection2 = true;
}
// DISTINCT plan node is rewrote with GROUP BY and adds above the original GROUP BY node
// there may be another projection node in between for complex aggregation case
boolean hasOrderby = false, hasLimit = false;
boolean groupByMergeReceive = false;
// infer the ORDERBY/LIMIT information from the base line query
if (apn2 instanceof OrderByPlanNode) {
hasOrderby = true;
if (apn2.getInlinePlanNode(PlanNodeType.LIMIT) != null) {
hasLimit = true;
}
apn2 = apn2.getChild(0);
} else if (apn2 instanceof LimitPlanNode) {
hasLimit = true;
apn2 = apn2.getChild(0);
} else if (apn2 instanceof MergeReceivePlanNode) {
assertTrue(apn2.getInlinePlanNode(PlanNodeType.ORDERBY) != null);
hasOrderby = true;
hasLimit = apn2.getInlinePlanNode(PlanNodeType.LIMIT) != null;
groupByMergeReceive = true;
}
// check the DISTINCT query plan
boolean distinctMergeReceive = false;
if (hasOrderby) {
if (apn1 instanceof OrderByPlanNode) {
assertTrue(apn1 instanceof OrderByPlanNode);
if (hasLimit) {
// check inline limit
assertNotNull(apn1.getInlinePlanNode(PlanNodeType.LIMIT));
}
apn1 = apn1.getChild(0);
} else if (apn1 instanceof MergeReceivePlanNode) {
distinctMergeReceive = true;
assertNotNull(apn1.getInlinePlanNode(PlanNodeType.ORDERBY));
assertEquals(0, apn1.getChildCount());
} else {
fail("The distinctSQL top node is not OrderBy or MergeReceive.");
}
} else if (hasLimit) {
assertTrue(apn1 instanceof LimitPlanNode);
apn1 = apn1.getChild(0);
}
// Check DISTINCT group by plan node
if (distinctMergeReceive) {
AbstractPlanNode aggr = AggregatePlanNode.getInlineAggregationNode(apn1);
assertTrue(aggr instanceof AggregatePlanNode);
assertEquals(0, ((AggregatePlanNode) aggr).getAggregateTypesSize());
assertEquals(pns1.get(0).getOutputSchema().getColumns().size(), ((AggregatePlanNode) aggr).getGroupByExpressionsSize());
if (hasLimit) {
// check inline limit
assertNotNull(aggr.getInlinePlanNode(PlanNodeType.LIMIT));
}
} else {
assertTrue(apn1 instanceof HashAggregatePlanNode);
assertEquals(0, ((HashAggregatePlanNode) apn1).getAggregateTypesSize());
assertEquals(pns1.get(0).getOutputSchema().getColumns().size(), ((HashAggregatePlanNode) apn1).getGroupByExpressionsSize());
apn1 = apn1.getChild(0);
}
// check projection node for complex aggregation case
if (apn1 instanceof ProjectionPlanNode) {
apn1 = apn1.getChild(0);
assertFalse(hasTopProjection1);
}
if (apn2 instanceof ProjectionPlanNode) {
apn2 = apn2.getChild(0);
assertFalse(hasTopProjection2);
}
// check the rest plan nodes.
if (distinctMergeReceive == false && groupByMergeReceive == false) {
assertEquals(apn1.toExplainPlanString(), apn2.toExplainPlanString());
} else if (distinctMergeReceive == true && groupByMergeReceive == true) {
// In case of applied MergeReceive optimization the apn1 and apn2 nodes
// should not have any children
assertEquals(0, apn1.getChildCount());
assertEquals(0, apn2.getChildCount());
}
// Distributed DISTINCT GROUP BY
if (pns1.size() > 1) {
if (!limitPushdown) {
assertEquals(pns1.get(1).toExplainPlanString(), pns2.get(1).toExplainPlanString());
return;
}
assertTrue(pns1.get(1) instanceof SendPlanNode);
assertTrue(pns2.get(1) instanceof SendPlanNode);
apn1 = pns1.get(1).getChild(0);
apn2 = pns2.get(1).getChild(0);
// ignore the ORDER BY/LIMIT pushdown plan node
// because DISTINCT case can not be pushed down
assertTrue(apn2 instanceof OrderByPlanNode);
assertNotNull(apn2.getInlinePlanNode(PlanNodeType.LIMIT));
apn2 = apn2.getChild(0);
// winners may produce completely different paths.
if (distinctMergeReceive == false && groupByMergeReceive == false) {
assertEquals(apn1.toExplainPlanString(), apn2.toExplainPlanString());
}
}
}
use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class PlanAssembler method checkLimitPushDownViability.
/**
* Check if we can push the limit node down.
*
* Return a mid-plan send node, if one exists and can host a
* distributed limit node.
* There is guaranteed to be at most a single receive/send pair.
* Abort the search if a node that a "limit" can't be pushed past
* is found before its receive node.
*
* Can only push past:
* * coordinatingAggregator: a distributed aggregator
* a copy of which has already been pushed down.
* Distributing a LIMIT to just above that aggregator is correct.
* (I've got some doubts that this is correct??? --paul)
*
* * order by: if the plan requires a sort, getNextSelectPlan()
* will have already added an ORDER BY.
* A distributed LIMIT will be added above a copy
* of that ORDER BY node.
*
* * projection: these have no effect on the application of limits.
*
* @param root
* @return If we can push the limit down, the send plan node is returned.
* Otherwise null -- when the plan is single-partition when
* its "coordinator" part contains a push-blocking node type.
*/
protected AbstractPlanNode checkLimitPushDownViability(AbstractPlanNode root) {
AbstractPlanNode receiveNode = root;
List<ParsedColInfo> orderBys = m_parsedSelect.orderByColumns();
boolean orderByCoversAllGroupBy = m_parsedSelect.groupByIsAnOrderByPermutation();
while (!(receiveNode instanceof ReceivePlanNode)) {
// TODO: We might want to optimize/push down "limit" for some cases
if (!(receiveNode instanceof OrderByPlanNode) && !(receiveNode instanceof ProjectionPlanNode) && !isValidAggregateNodeForLimitPushdown(receiveNode, orderBys, orderByCoversAllGroupBy)) {
return null;
}
if (receiveNode instanceof OrderByPlanNode) {
// limit can still push down if ordered by aggregate values.
if (!m_parsedSelect.hasPartitionColumnInGroupby() && isOrderByAggregationValue(m_parsedSelect.orderByColumns())) {
return null;
}
}
// Traverse...
if (receiveNode.getChildCount() == 0) {
return null;
}
// nothing that allows pushing past has multiple inputs
assert (receiveNode.getChildCount() == 1);
receiveNode = receiveNode.getChild(0);
}
return receiveNode.getChild(0);
}
use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class PlanAssembler method handleOrderBy.
/**
* Create an order by node as required by the statement and make it a parent of root.
* @param parsedStmt Parsed statement, for context
* @param root The root of the plan needing ordering
* @return new orderByNode (the new root) or the original root if no orderByNode was required.
*/
private static AbstractPlanNode handleOrderBy(AbstractParsedStmt parsedStmt, AbstractPlanNode root) {
assert (parsedStmt instanceof ParsedSelectStmt || parsedStmt instanceof ParsedUnionStmt || parsedStmt instanceof ParsedDeleteStmt);
if (!isOrderByNodeRequired(parsedStmt, root)) {
return root;
}
OrderByPlanNode orderByNode = buildOrderByPlanNode(parsedStmt.orderByColumns());
orderByNode.addAndLinkChild(root);
return orderByNode;
}
Aggregations