use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class TestWindowedFunctions method validateWindowedFunctionPlan.
/**
* Validate that each similar windowed query in testRank produces a similar
* plan, with the expected minor variation to its ORDER BY node.
* @param windowedQuery a variant of a test query of a known basic format
* @param nSorts the expected number of sort criteria that should have been
* extracted from the variant query's PARTITION BY and ORDER BY.
* @param descSortIndex the position among the sort criteria of the original
* ORDER BY column, always distinguishable by its "DESC" direction.
**/
private void validateWindowedFunctionPlan(String windowedQuery, int nSorts, int descSortIndex, int numPartitionExprs, ExpressionType winOpType) {
// Sometimes we get multi-fragment nodes when we
// expect single fragment nodes. Keeping all the fragments
// helps to diagnose the problem.
List<AbstractPlanNode> nodes = compileToFragments(windowedQuery);
assertEquals(1, nodes.size());
AbstractPlanNode node = nodes.get(0);
// The plan should look like:
// SendNode -> ProjectionPlanNode -> PartitionByPlanNode -> OrderByPlanNode -> SeqScanNode
// We also do some sanity checking on the PartitionPlan node.
// First dissect the plan.
assertTrue(node instanceof SendPlanNode);
AbstractPlanNode projPlanNode = node.getChild(0);
assertTrue(projPlanNode instanceof ProjectionPlanNode);
AbstractPlanNode windowFuncPlanNode = projPlanNode.getChild(0);
assertTrue(windowFuncPlanNode instanceof WindowFunctionPlanNode);
AbstractPlanNode abstractOrderByNode = windowFuncPlanNode.getChild(0);
assertTrue(abstractOrderByNode instanceof OrderByPlanNode);
OrderByPlanNode orderByNode = (OrderByPlanNode) abstractOrderByNode;
NodeSchema input_schema = orderByNode.getOutputSchema();
assertNotNull(input_schema);
AbstractPlanNode seqScanNode = orderByNode.getChild(0);
assertTrue(seqScanNode instanceof SeqScanPlanNode || seqScanNode instanceof NestLoopPlanNode);
WindowFunctionPlanNode wfPlanNode = (WindowFunctionPlanNode) windowFuncPlanNode;
NodeSchema schema = wfPlanNode.getOutputSchema();
//
// Check that the window function plan node's output schema is correct.
// Look at the first expression, to verify that it's the windowed expression.
// Then check that the TVEs all make sense.
//
SchemaColumn column = schema.getColumns().get(0);
assertEquals("ARANK", column.getColumnAlias());
assertEquals(numPartitionExprs, wfPlanNode.getPartitionByExpressions().size());
validateTVEs(input_schema, wfPlanNode, false);
//
// Check that the operation is what we expect.
//
assertTrue(wfPlanNode.getAggregateTypes().size() > 0);
assertEquals(winOpType, wfPlanNode.getAggregateTypes().get(0));
//
for (List<AbstractExpression> exprs : wfPlanNode.getAggregateExpressions()) {
if (exprs != null) {
for (AbstractExpression expr : exprs) {
assertNotNull(expr.getValueType());
}
}
}
//
// Check that the order by node has the right number of expressions.
// and that they have the correct order.
//
assertEquals(nSorts, orderByNode.getSortExpressions().size());
int sortIndex = 0;
for (SortDirectionType direction : orderByNode.getSortDirections()) {
SortDirectionType expected = (sortIndex == descSortIndex) ? SortDirectionType.DESC : SortDirectionType.ASC;
assertEquals(expected, direction);
++sortIndex;
}
}
use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class TestWindowedFunctions method validateQueryWithSubquery.
/**
* Validate that each similar windowed query in testRankWithSubqueries
* produces a similar plan
* @param windowedQuery a variant of a test query of a known basic format
**/
private void validateQueryWithSubquery(String windowedQuery, boolean waiveAliasMatch) {
AbstractPlanNode node = compile(windowedQuery);
// Dissect the plan.
assertTrue(node instanceof SendPlanNode);
AbstractPlanNode projectionPlanNode = node.getChild(0);
assertTrue(projectionPlanNode instanceof ProjectionPlanNode);
AbstractPlanNode partitionByPlanNode = projectionPlanNode.getChild(0);
assertTrue(partitionByPlanNode instanceof WindowFunctionPlanNode);
AbstractPlanNode orderByPlanNode = partitionByPlanNode.getChild(0);
assertTrue(orderByPlanNode instanceof OrderByPlanNode);
NodeSchema input_schema = orderByPlanNode.getOutputSchema();
AbstractPlanNode scanNode = orderByPlanNode.getChild(0);
assertTrue(scanNode instanceof NestLoopPlanNode);
NodeSchema schema = partitionByPlanNode.getOutputSchema();
SchemaColumn column = schema.getColumns().get(0);
assertEquals("ARANK", column.getColumnAlias());
validateTVEs(input_schema, (WindowFunctionPlanNode) partitionByPlanNode, waiveAliasMatch);
}
use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class TestUnion method testSubqueryUnionWithParamENG7783.
public void testSubqueryUnionWithParamENG7783() {
AbstractPlanNode pn = compile("SELECT B, ABS( B - ? ) AS distance FROM ( " + "( SELECT B FROM T2 WHERE B >=? ORDER BY B LIMIT ? " + ") UNION ALL ( " + "SELECT B FROM T2 WHERE B < ? ORDER BY B DESC LIMIT ? ) " + ") AS n ORDER BY distance LIMIT ?;");
assertTrue(pn.getChild(0) instanceof ProjectionPlanNode);
assertTrue(pn.getChild(0).getChild(0) instanceof OrderByPlanNode);
assertTrue(pn.getChild(0).getChild(0).getChild(0) instanceof SeqScanPlanNode);
assertTrue(pn.getChild(0).getChild(0).getChild(0).getChild(0) instanceof UnionPlanNode);
}
use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class PlanAssembler method getNextDeletePlan.
private CompiledPlan getNextDeletePlan() {
assert (m_subAssembler != null);
// figure out which table we're deleting from
assert (m_parsedDelete.m_tableList.size() == 1);
Table targetTable = m_parsedDelete.m_tableList.get(0);
AbstractPlanNode subSelectRoot = m_subAssembler.nextPlan();
if (subSelectRoot == null) {
return null;
}
// ENG-4909 Bug: currently disable NESTLOOPINDEX plan for IN
if (disableNestedLoopIndexJoinForInComparison(subSelectRoot, m_parsedDelete)) {
// simply jumps ahead to the next plan (if any).
return getNextDeletePlan();
}
boolean isSinglePartitionPlan = m_partitioning.wasSpecifiedAsSingle() || m_partitioning.isInferredSingle();
// generate the delete node with the right target table
DeletePlanNode deleteNode = new DeletePlanNode();
deleteNode.setTargetTableName(targetTable.getTypeName());
assert (subSelectRoot instanceof AbstractScanPlanNode);
// nodes and use a truncate delete node.
if (deleteIsTruncate(m_parsedDelete, subSelectRoot)) {
deleteNode.setTruncate(true);
} else {
// User may have specified an ORDER BY ... LIMIT clause
if (m_parsedDelete.orderByColumns().size() > 0 && !isSinglePartitionPlan && !targetTable.getIsreplicated()) {
throw new PlanningErrorException("DELETE statements affecting partitioned tables must " + "be able to execute on one partition " + "when ORDER BY and LIMIT or OFFSET clauses " + "are present.");
}
boolean needsOrderByNode = isOrderByNodeRequired(m_parsedDelete, subSelectRoot);
AbstractExpression addressExpr = new TupleAddressExpression();
NodeSchema proj_schema = new NodeSchema();
// This planner-created column is magic.
proj_schema.addColumn(AbstractParsedStmt.TEMP_TABLE_NAME, AbstractParsedStmt.TEMP_TABLE_NAME, "tuple_address", "tuple_address", addressExpr);
if (needsOrderByNode) {
// Projection will need to pass the sort keys to the order by node
for (ParsedColInfo col : m_parsedDelete.orderByColumns()) {
proj_schema.addColumn(col.asSchemaColumn());
}
}
ProjectionPlanNode projectionNode = new ProjectionPlanNode(proj_schema);
subSelectRoot.addInlinePlanNode(projectionNode);
AbstractPlanNode root = subSelectRoot;
if (needsOrderByNode) {
OrderByPlanNode ob = buildOrderByPlanNode(m_parsedDelete.orderByColumns());
ob.addAndLinkChild(root);
root = ob;
}
if (m_parsedDelete.hasLimitOrOffset()) {
assert (m_parsedDelete.orderByColumns().size() > 0);
root.addInlinePlanNode(m_parsedDelete.limitPlanNode());
}
deleteNode.addAndLinkChild(root);
}
CompiledPlan plan = new CompiledPlan();
plan.setReadOnly(false);
// check non-determinism status
// treat this as deterministic for reporting purposes:
// delete statements produce just one row that is the
// number of rows affected
boolean orderIsDeterministic = true;
boolean hasLimitOrOffset = m_parsedDelete.hasLimitOrOffset();
// The delete statement cannot be inherently content non-deterministic.
// So, the last parameter is always null.
plan.statementGuaranteesDeterminism(hasLimitOrOffset, orderIsDeterministic, null);
if (isSinglePartitionPlan) {
plan.rootPlanGraph = deleteNode;
return plan;
}
// Add a compensating sum of modified tuple counts or a limit 1
// AND a send on top of the union-like receive node.
boolean isReplicated = targetTable.getIsreplicated();
plan.rootPlanGraph = addCoordinatorToDMLNode(deleteNode, isReplicated);
return plan;
}
use of org.voltdb.plannodes.OrderByPlanNode in project voltdb by VoltDB.
the class TestPlansLimit method checkInlineLimitAndOrderbyWithReceive.
private void checkInlineLimitAndOrderbyWithReceive(List<AbstractPlanNode> pns, boolean pushdown) {
AbstractPlanNode p;
p = pns.get(0).getChild(0);
assertTrue(p instanceof ProjectionPlanNode);
p = p.getChild(0);
assertTrue(p instanceof MergeReceivePlanNode);
assertNotNull(p.getInlinePlanNode(PlanNodeType.LIMIT));
assertNotNull(p.getInlinePlanNode(PlanNodeType.ORDERBY));
if (pushdown) {
assertEquals(2, pns.size());
p = pns.get(1).getChild(0);
assertTrue(p instanceof OrderByPlanNode);
assertNotNull(p.getInlinePlanNode(PlanNodeType.LIMIT));
} else if (pns.size() == 2) {
p = pns.get(1).getChild(0);
assertFalse(p.toExplainPlanString().toLowerCase().contains("limit"));
}
}
Aggregations