use of org.voltdb.plannodes.LimitPlanNode in project voltdb by VoltDB.
the class PlanAssembler method addCoordinatorToDMLNode.
/**
* Add a receive node, a sum or limit node, and a send node to the given DML node.
* If the DML target is a replicated table, it will add a limit node,
* otherwise it adds a sum node.
*
* @param dmlRoot
* @param isReplicated Whether or not the target table is a replicated table.
* @return
*/
private static AbstractPlanNode addCoordinatorToDMLNode(AbstractPlanNode dmlRoot, boolean isReplicated) {
dmlRoot = SubPlanAssembler.addSendReceivePair(dmlRoot);
AbstractPlanNode sumOrLimitNode;
if (isReplicated) {
// Replicated table DML result doesn't need to be summed. All partitions should
// modify the same number of tuples in replicated table, so just pick the result from
// any partition.
LimitPlanNode limitNode = new LimitPlanNode();
sumOrLimitNode = limitNode;
limitNode.setLimit(1);
} else {
// create the nodes being pushed on top of dmlRoot.
AggregatePlanNode countNode = new AggregatePlanNode();
sumOrLimitNode = countNode;
// configure the count aggregate (sum) node to produce a single
// output column containing the result of the sum.
// Create a TVE that should match the tuple count input column
// This TVE is magic.
// really really need to make this less hard-wired
TupleValueExpression count_tve = new TupleValueExpression(AbstractParsedStmt.TEMP_TABLE_NAME, AbstractParsedStmt.TEMP_TABLE_NAME, "modified_tuples", "modified_tuples", 0);
count_tve.setValueType(VoltType.BIGINT);
count_tve.setValueSize(VoltType.BIGINT.getLengthInBytesForFixedTypes());
countNode.addAggregate(ExpressionType.AGGREGATE_SUM, false, 0, count_tve);
// The output column. Not really based on a TVE (it is really the
// count expression represented by the count configured above). But
// this is sufficient for now. This looks identical to the above
// TVE but it's logically different so we'll create a fresh one.
TupleValueExpression tve = new TupleValueExpression(AbstractParsedStmt.TEMP_TABLE_NAME, AbstractParsedStmt.TEMP_TABLE_NAME, "modified_tuples", "modified_tuples", 0);
tve.setValueType(VoltType.BIGINT);
tve.setValueSize(VoltType.BIGINT.getLengthInBytesForFixedTypes());
NodeSchema count_schema = new NodeSchema();
count_schema.addColumn(AbstractParsedStmt.TEMP_TABLE_NAME, AbstractParsedStmt.TEMP_TABLE_NAME, "modified_tuples", "modified_tuples", tve);
countNode.setOutputSchema(count_schema);
}
// connect the nodes to build the graph
sumOrLimitNode.addAndLinkChild(dmlRoot);
SendPlanNode sendNode = new SendPlanNode();
sendNode.addAndLinkChild(sumOrLimitNode);
return sendNode;
}
use of org.voltdb.plannodes.LimitPlanNode 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.LimitPlanNode in project voltdb by VoltDB.
the class TestPlansInExistsSubQueries method testInAggregated.
public void testInAggregated() {
AbstractPlanNode pn = compile("select a, sum(c) as sc1 from r1 where (a, c) in " + "( SELECT a, count(c) as sc2 " + "from r1 GROUP BY a ORDER BY a DESC) GROUP BY A;");
pn = pn.getChild(0);
assertTrue(pn instanceof AbstractScanPlanNode);
AbstractExpression e = ((AbstractScanPlanNode) pn).getPredicate();
assertEquals(ExpressionType.OPERATOR_EXISTS, e.getExpressionType());
AbstractSubqueryExpression subExpr = (AbstractSubqueryExpression) e.getLeft();
AbstractPlanNode sn = subExpr.getSubqueryNode();
// Added LIMIT 1
assertTrue(sn instanceof LimitPlanNode);
assertEquals(1, ((LimitPlanNode) sn).getLimit());
sn = sn.getChild(0);
assertTrue(sn instanceof SeqScanPlanNode);
AggregatePlanNode aggNode = AggregatePlanNode.getInlineAggregationNode(sn);
assertNotNull(aggNode.getPostPredicate());
}
use of org.voltdb.plannodes.LimitPlanNode in project voltdb by VoltDB.
the class InlineAggregation method inlineAggregationApply.
AbstractPlanNode inlineAggregationApply(AbstractPlanNode plan) {
// check for an aggregation of the right form
if (!(plan instanceof AggregatePlanNode)) {
return plan;
}
assert (plan.getChildCount() == 1);
AggregatePlanNode aggplan = (AggregatePlanNode) plan;
// Assuming all AggregatePlanNode has not been inlined before this microoptimization
AbstractPlanNode child = aggplan.getChild(0);
// EE Currently support: seqscan + indexscan
if (child.getPlanNodeType() != PlanNodeType.SEQSCAN && child.getPlanNodeType() != PlanNodeType.INDEXSCAN && child.getPlanNodeType() != PlanNodeType.NESTLOOP && child.getPlanNodeType() != PlanNodeType.NESTLOOPINDEX) {
return plan;
}
if (child.getPlanNodeType() == PlanNodeType.INDEXSCAN) {
// Currently do not conflict with the optimized MIN/MAX
// because of the big amount of tests changed.
IndexScanPlanNode isp = (IndexScanPlanNode) child;
LimitPlanNode limit = (LimitPlanNode) isp.getInlinePlanNode(PlanNodeType.LIMIT);
if (limit != null && (aggplan.isTableMin() || aggplan.isTableMax())) {
// Optimized MIN/MAX
if (limit.getLimit() == 1 && limit.getOffset() == 0) {
return plan;
}
}
}
// Inline aggregate node
AbstractPlanNode parent = null;
if (aggplan.getParentCount() == 1) {
parent = aggplan.getParent(0);
}
child.addInlinePlanNode(aggplan);
child.clearParents();
if (parent != null) {
parent.replaceChild(aggplan, child);
}
return child;
}
use of org.voltdb.plannodes.LimitPlanNode in project voltdb by VoltDB.
the class TestPlansInExistsSubQueries method testHavingInSubquery.
public void testHavingInSubquery() {
String sql;
AbstractPlanNode pn;
AggregatePlanNode aggNode;
List<AbstractExpression> args;
AbstractExpression pred;
AbstractSubqueryExpression sqe;
AbstractExpression postExpr;
AbstractExpression re;
AbstractExpression le;
// filter on agg of expression involving grand-parent tve
sql = "select a from r1 where exists " + "(select 1 from r2 where exists " + " (select 1 from r3 group by c having min(a) > r1.d)) ";
pn = compile(sql);
pn = pn.getChild(0);
assertTrue(pn instanceof SeqScanPlanNode);
pred = ((SeqScanPlanNode) pn).getPredicate();
// child
assertEquals(ExpressionType.OPERATOR_EXISTS, pred.getExpressionType());
sqe = (AbstractSubqueryExpression) pred.getLeft();
//* enable to debug */ System.out.println(se.explain(""));
args = sqe.getArgs();
assertEquals(1, args.size());
assertEquals(1, sqe.getParameterIdxList().size());
assertEquals("D", ((TupleValueExpression) args.get(0)).getColumnName());
pn = sqe.getSubqueryNode();
assertTrue(pn instanceof SeqScanPlanNode);
pred = ((SeqScanPlanNode) pn).getPredicate();
// grand child
assertEquals(ExpressionType.OPERATOR_EXISTS, pred.getExpressionType());
sqe = (AbstractSubqueryExpression) pred.getLeft();
pn = sqe.getSubqueryNode();
pn = pn.getChild(0).getChild(0);
aggNode = AggregatePlanNode.getInlineAggregationNode(pn);
assertNotNull(aggNode);
postExpr = aggNode.getPostPredicate();
assertNotNull(postExpr);
assertEquals(ExpressionType.COMPARE_GREATERTHAN, postExpr.getExpressionType());
re = postExpr.getRight();
assertEquals(ExpressionType.VALUE_PARAMETER, re.getExpressionType());
assertEquals(new Integer(0), ((ParameterValueExpression) re).getParameterIndex());
// filter on agg of expression involving parent tve
sql = "select a from r1 where c in " + " (select max(c) from r2 group by e having min(a) > r1.d)";
pn = compile(sql);
pn = pn.getChild(0);
assertTrue(pn instanceof SeqScanPlanNode);
pred = ((SeqScanPlanNode) pn).getPredicate();
assertEquals(ExpressionType.OPERATOR_EXISTS, pred.getExpressionType());
sqe = (AbstractSubqueryExpression) pred.getLeft();
args = sqe.getArgs();
assertEquals(2, args.size());
assertEquals(2, sqe.getParameterIdxList().size());
assertEquals("D", ((TupleValueExpression) args.get(0)).getColumnName());
assertEquals("C", ((TupleValueExpression) args.get(1)).getColumnName());
pn = sqe.getSubqueryNode();
pn = pn.getChild(0);
assertTrue(pn instanceof LimitPlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof SeqScanPlanNode);
aggNode = AggregatePlanNode.getInlineAggregationNode(pn);
assertNotNull(aggNode);
assertEquals(3, aggNode.getOutputSchema().size());
postExpr = aggNode.getPostPredicate();
assertEquals(ExpressionType.CONJUNCTION_AND, postExpr.getExpressionType());
le = postExpr.getLeft();
assertEquals(ExpressionType.COMPARE_GREATERTHAN, le.getExpressionType());
assertEquals(new Integer(0), ((ParameterValueExpression) le.getRight()).getParameterIndex());
re = postExpr.getRight();
assertEquals(ExpressionType.COMPARE_EQUAL, re.getExpressionType());
assertEquals(new Integer(1), ((ParameterValueExpression) re.getLeft()).getParameterIndex());
// filter on agg of expression involving user parameter ('?')
sql = "select a from r1 where c in " + " (select max(c) from r2 group by e having min(a) > ?) ";
pn = compile(sql);
pn = pn.getChild(0);
assertTrue(pn instanceof SeqScanPlanNode);
pred = ((SeqScanPlanNode) pn).getPredicate();
assertEquals(ExpressionType.OPERATOR_EXISTS, pred.getExpressionType());
sqe = (AbstractSubqueryExpression) pred.getLeft();
assertEquals(1, sqe.getParameterIdxList().size());
assertEquals(new Integer(1), sqe.getParameterIdxList().get(0));
pn = sqe.getSubqueryNode();
pn = pn.getChild(0).getChild(0);
assertEquals(PlanNodeType.SEQSCAN, pn.getPlanNodeType());
aggNode = AggregatePlanNode.getInlineAggregationNode(pn);
assertNotNull(aggNode);
postExpr = aggNode.getPostPredicate();
assertEquals(ExpressionType.CONJUNCTION_AND, postExpr.getExpressionType());
// User PVE
le = postExpr.getLeft();
assertEquals(ExpressionType.COMPARE_GREATERTHAN, le.getExpressionType());
assertEquals(ExpressionType.VALUE_PARAMETER, le.getRight().getExpressionType());
assertEquals(new Integer(0), ((ParameterValueExpression) le.getRight()).getParameterIndex());
// Parent PVE
re = postExpr.getRight();
assertEquals(ExpressionType.COMPARE_EQUAL, re.getExpressionType());
assertEquals(ExpressionType.VALUE_PARAMETER, re.getLeft().getExpressionType());
assertEquals(new Integer(1), ((ParameterValueExpression) re.getLeft()).getParameterIndex());
// filter on agg of local tve
sql = "select a from r1 where c in " + " (select max(c) from r2 group by e having min(a) > 0)";
pn = compile(sql);
pn = pn.getChild(0);
assertTrue(pn instanceof SeqScanPlanNode);
AbstractExpression p = ((SeqScanPlanNode) pn).getPredicate();
assertEquals(ExpressionType.OPERATOR_EXISTS, p.getExpressionType());
AbstractExpression subquery = p.getLeft();
pn = ((AbstractSubqueryExpression) subquery).getSubqueryNode();
pn = pn.getChild(0);
assertTrue(pn instanceof LimitPlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof SeqScanPlanNode);
aggNode = AggregatePlanNode.getInlineAggregationNode(pn);
assertNotNull(aggNode);
assertEquals(3, aggNode.getOutputSchema().size());
postExpr = aggNode.getPostPredicate();
assertEquals(ExpressionType.CONJUNCTION_AND, postExpr.getExpressionType());
failToCompile("select max(c) from r1 group by a " + " having count(*) = (select c from r2 where r2.c = r1.a)", HavingErrorMsg);
/**
* Uncomment these tests when ENG-8306 is finished
*/
// // parent correlated TVE in the aggregate expression.
// sql = "select max(c) from r1 group by a " +
// " having count(*) = (select c from r2 where r2.c = r1.a)";
// pn = compile(sql);
// pn = pn.getChild(0);
// assertTrue(pn instanceof ProjectionPlanNode);
// pn = pn.getChild(0);
// assertTrue(pn instanceof SeqScanPlanNode);
// aggNode = AggregatePlanNode.getInlineAggregationNode(pn);
// assertNotNull(aggNode);
// assertNotNull(aggNode instanceof HashAggregatePlanNode);
// assertEquals(3, aggNode.getOutputSchema().size()); // group by key, max, count
//
// postExpr = aggNode.getPostPredicate();
// assertEquals(ExpressionType.COMPARE_EQUAL, postExpr.getExpressionType());
// assertTrue(postExpr.getLeft() instanceof TupleValueExpression);
// assertTrue(postExpr.getRight() instanceof SelectSubqueryExpression);
}
Aggregations