use of org.voltdb.plannodes.ProjectionPlanNode in project voltdb by VoltDB.
the class TestSelfJoins method testSelfJoin.
public void testSelfJoin() {
AbstractPlanNode pn = compile("select * FROM R1 A JOIN R1 B ON A.C = B.C WHERE B.A > 0 AND A.C < 3");
pn = pn.getChild(0).getChild(0);
assertTrue(pn instanceof NestLoopPlanNode);
assertEquals(4, pn.getOutputSchema().getColumns().size());
assertEquals(2, pn.getChildCount());
AbstractPlanNode c = pn.getChild(0);
assertTrue(c instanceof SeqScanPlanNode);
SeqScanPlanNode ss = (SeqScanPlanNode) c;
assertEquals("R1", ss.getTargetTableName());
assertEquals("A", ss.getTargetTableAlias());
assertEquals(ExpressionType.COMPARE_LESSTHAN, ss.getPredicate().getExpressionType());
c = pn.getChild(1);
assertTrue(c instanceof SeqScanPlanNode);
ss = (SeqScanPlanNode) c;
assertEquals("R1", ss.getTargetTableName());
assertEquals("B", ss.getTargetTableAlias());
assertEquals(ExpressionType.COMPARE_GREATERTHAN, ss.getPredicate().getExpressionType());
pn = compile("select * FROM R1 JOIN R1 B ON R1.C = B.C");
pn = pn.getChild(0).getChild(0);
assertTrue(pn instanceof NestLoopPlanNode);
assertEquals(4, pn.getOutputSchema().getColumns().size());
assertEquals(2, pn.getChildCount());
c = pn.getChild(0);
assertTrue(c instanceof SeqScanPlanNode);
ss = (SeqScanPlanNode) c;
assertEquals("R1", ss.getTargetTableName());
assertEquals("R1", ss.getTargetTableAlias());
c = pn.getChild(1);
assertTrue(c instanceof SeqScanPlanNode);
ss = (SeqScanPlanNode) c;
assertEquals("R1", ss.getTargetTableName());
assertEquals("B", ss.getTargetTableAlias());
pn = compile("select A.A, A.C, B.A, B.C FROM R1 A JOIN R1 B ON A.C = B.C");
pn = pn.getChild(0).getChild(0);
assertTrue(pn instanceof NestLoopPlanNode);
assertEquals(4, pn.getOutputSchema().getColumns().size());
pn = compile("select A,B.C FROM R1 A JOIN R2 B USING(A)");
pn = pn.getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
NodeSchema ns = pn.getOutputSchema();
for (SchemaColumn sc : ns.getColumns()) {
AbstractExpression e = sc.getExpression();
assertTrue(e instanceof TupleValueExpression);
TupleValueExpression tve = (TupleValueExpression) e;
assertNotSame(-1, tve.getColumnIndex());
}
}
use of org.voltdb.plannodes.ProjectionPlanNode in project voltdb by VoltDB.
the class TestSelfJoins method testIndexedSelfJoin.
public void testIndexedSelfJoin() {
AbstractPlanNode.enableVerboseExplainForDebugging();
IndexScanPlanNode c;
AbstractPlanNode apn;
AbstractPlanNode pn;
NestLoopIndexPlanNode nlij;
List<AbstractExpression> searchKeys;
// SELF JOIN using two different indexes on the same table
// sometimes with a surviving sort ordering that supports GROUP BY and/or ORDER BY.
apn = compile("select * FROM R2 A, R2 B WHERE A.A = B.A AND B.C > 1 ORDER BY B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
// Some day, the wasteful projection node will not be here to skip.
pn = apn.getChild(0).getChild(0);
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
c = (IndexScanPlanNode) nlij.getChild(0);
assertNull(c.getPredicate());
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
apn = compile("select * FROM R2 A, R2 B WHERE A.A = B.A AND B.C > 1 ORDER BY B.A, B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
// Some day, the wasteful projection node will not be here to skip.
pn = apn.getChild(0).getChild(0);
assertTrue(pn instanceof OrderByPlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
c = (IndexScanPlanNode) nlij.getChild(0);
assertNull(c.getPredicate());
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
apn = compile("select * FROM R2 A, R2 B WHERE A.A = B.A AND B.A > 1 ORDER BY B.A, B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
// Some day, the wasteful projection node will not be here to skip.
pn = apn.getChild(0).getChild(0);
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
assertTrue(nlij.getChild(0) instanceof IndexScanPlanNode);
c = (IndexScanPlanNode) nlij.getChild(0);
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
apn = compile("select B.C, MAX(A.C) FROM R2 A, R2 B WHERE A.A = B.A AND B.C > 1 GROUP BY B.C ORDER BY B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
// Some day, the wasteful projection node will not be here to skip.
pn = apn.getChild(0);
assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
c = (IndexScanPlanNode) nlij.getChild(0);
assertNull(c.getPredicate());
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
apn = compile("select B.C, B.A FROM R2 A, R2 B WHERE A.A = B.A AND B.C > 1 GROUP BY B.A, B.C ORDER BY B.A, B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
// Some day, the wasteful projection node will not be here to skip.
pn = apn.getChild(0).getChild(0);
assertTrue(pn instanceof OrderByPlanNode);
pn = pn.getChild(0);
assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
c = (IndexScanPlanNode) nlij.getChild(0);
assertNull(c.getPredicate());
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
apn = compile("select B.C, B.A FROM R2 A, R2 B WHERE A.A = B.A AND B.A > 1 GROUP BY B.A, B.C ORDER BY B.A, B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
pn = apn.getChild(0);
assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
assertTrue(nlij.getChild(0) instanceof IndexScanPlanNode);
c = (IndexScanPlanNode) nlij.getChild(0);
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
// Here's a case that can't be optimized because it purposely uses the "wrong" column
// in the GROUP BY and ORDER BY.
apn = compile("select B.C FROM R2 A, R2 B WHERE B.A = A.A AND B.C > 1 GROUP BY A.A, B.C ORDER BY A.A, B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
// Complex ORDER BY case: GROUP BY column that is not in the display column list
pn = apn.getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof OrderByPlanNode);
pn = pn.getChild(0);
assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
c = (IndexScanPlanNode) nlij.getChild(0);
assertNull(c.getPredicate());
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
// Here's a case that can't be optimized because it purposely uses the "wrong" column
// in the GROUP BY and ORDER BY.
apn = compile("select B.C FROM R2 A, R2 B WHERE B.A = A.A AND B.C > 1 GROUP BY A.A, B.C ORDER BY B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
// Project-first case: GROUP BY column that is not in the order by or the display column list
pn = apn.getChild(0);
assertTrue(pn instanceof OrderByPlanNode);
pn = pn.getChild(0);
//TODO: This represents a missed optimization.
// The projection could have been inlined.
assertTrue(pn instanceof ProjectionPlanNode);
pn = pn.getChild(0);
assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
c = (IndexScanPlanNode) nlij.getChild(0);
assertNull(c.getPredicate());
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
// This variant shows that the GROUP BY can be a permutation of the sort order
// without messing up the optimization
apn = compile("select B.C, B.A FROM R2 A, R2 B WHERE A.A = B.A AND B.A > 1 GROUP BY B.C, B.A ORDER BY B.A, B.C");
//* for debug */ System.out.println(apn.toExplainPlanString());
// Some day, the wasteful projection node will not be here to skip.
pn = apn.getChild(0);
assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
assertTrue(pn instanceof NestLoopIndexPlanNode);
nlij = (NestLoopIndexPlanNode) pn;
assertNull(nlij.getPreJoinPredicate());
assertNull(nlij.getJoinPredicate());
assertNull(nlij.getWherePredicate());
assertEquals(1, nlij.getChildCount());
assertTrue(nlij.getChild(0) instanceof IndexScanPlanNode);
c = (IndexScanPlanNode) nlij.getChild(0);
assertEquals(IndexLookupType.GT, c.getLookupType());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
assertEquals(IndexLookupType.GTE, c.getLookupType());
assertNull(c.getPredicate());
searchKeys = c.getSearchKeyExpressions();
assertEquals(1, searchKeys.size());
assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
}
use of org.voltdb.plannodes.ProjectionPlanNode in project voltdb by VoltDB.
the class TestWindowedFunctions method validatePartitionedQuery.
private void validatePartitionedQuery(String query, boolean hasStatementOrderBy) {
List<AbstractPlanNode> nodes = compileToFragments(query);
assertEquals(2, nodes.size());
AbstractPlanNode child = nodes.get(0);
// Validate the coordinator fragment.
assertTrue(child instanceof SendPlanNode);
child = child.getChild(0);
assertTrue(child instanceof ProjectionPlanNode);
if (hasStatementOrderBy) {
child = child.getChild(0);
assertTrue(child instanceof OrderByPlanNode);
}
child = child.getChild(0);
assertTrue(child instanceof WindowFunctionPlanNode);
child = child.getChild(0);
assertTrue(child instanceof OrderByPlanNode);
child = child.getChild(0);
assertTrue(child instanceof ReceivePlanNode);
assertEquals(0, child.getChildCount());
// Get the distributed fragment.
child = nodes.get(1);
assertTrue(child instanceof SendPlanNode);
child = child.getChild(0);
assertTrue(child instanceof SeqScanPlanNode);
assertEquals(0, child.getChildCount());
}
use of org.voltdb.plannodes.ProjectionPlanNode 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.ProjectionPlanNode in project voltdb by VoltDB.
the class TestPlansSubQueries method testJoins.
public void testJoins() {
AbstractPlanNode pn;
List<AbstractPlanNode> planNodes;
AbstractPlanNode nlpn;
String sql, sqlNoSimplification, equivalentSql;
// Left Outer join
sql = "SELECT R1.A, R1.C FROM R1 LEFT JOIN (SELECT A, C FROM R2) T1 ON T1.C = R1.C ";
sqlNoSimplification = "SELECT R1.A, R1.C FROM R1 LEFT JOIN (SELECT A, C FROM R2 LIMIT 10) T1 ON T1.C = R1.C ";
equivalentSql = "SELECT R1.A, R1.C FROM R1 LEFT JOIN R2 T1 ON T1.C = R1.C ";
planNodes = compileToFragments(sqlNoSimplification);
assertEquals(1, planNodes.size());
pn = planNodes.get(0).getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopPlanNode);
assertEquals(JoinType.LEFT, ((NestLoopPlanNode) nlpn).getJoinType());
pn = nlpn.getChild(0);
checkSeqScan(pn, "R1", "A", "C");
pn = nlpn.getChild(1);
checkSeqScan(pn, "T1", "C");
pn = pn.getChild(0);
checkSeqScan(pn, "R2", "A", "C");
checkSubquerySimplification(sql, equivalentSql);
// Join with partitioned tables
// Join on coordinator: LEFT OUTER JOIN, replicated table on left side
sql = "SELECT R1.A, R1.C FROM R1 LEFT JOIN (SELECT A, C FROM P1) T1 ON T1.C = R1.C ";
sqlNoSimplification = "SELECT R1.A, R1.C FROM R1 LEFT JOIN (SELECT DISTINCT A, C FROM P1) T1 ON T1.C = R1.C ";
equivalentSql = "SELECT R1.A, R1.C FROM R1 LEFT JOIN P1 T1 ON T1.C = R1.C ";
planNodes = compileToFragments(sqlNoSimplification);
assertEquals(2, planNodes.size());
pn = planNodes.get(0).getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopPlanNode);
assertEquals(JoinType.LEFT, ((NestLoopPlanNode) nlpn).getJoinType());
pn = nlpn.getChild(0);
checkSeqScan(pn, "R1", "A", "C");
pn = nlpn.getChild(1);
assertEquals(PlanNodeType.RECEIVE, pn.getPlanNodeType());
pn = planNodes.get(1);
assertTrue(pn instanceof SendPlanNode);
pn = pn.getChild(0);
checkSeqScan(pn, "T1", "C");
checkSubquerySimplification(sql, equivalentSql);
// Group by inside of the subquery
// whether it contains group by or not does not matter, because we check it by whether inner side is partitioned or not
planNodes = compileToFragments("SELECT R1.A, R1.C FROM R1 LEFT JOIN (SELECT A, count(*) C FROM P1 GROUP BY A) T1 ON 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);
assertEquals(JoinType.LEFT, ((NestLoopPlanNode) nlpn).getJoinType());
pn = nlpn.getChild(0);
checkSeqScan(pn, "R1", "A", "C");
pn = nlpn.getChild(1);
assertTrue(pn instanceof ReceivePlanNode);
pn = planNodes.get(1);
assertTrue(pn instanceof SendPlanNode);
pn = pn.getChild(0);
checkSeqScan(pn, "T1", "C");
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1", "A", "C");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
// Using index scan for group by only: use serial aggregate instead hash aggregate
assertNotNull(pn.getInlinePlanNode(PlanNodeType.AGGREGATE));
// LEFT partition table
planNodes = compileToFragments("SELECT T1.CC FROM P1 LEFT JOIN (SELECT A, count(*) CC FROM P2 GROUP BY A) T1 ON T1.A = P1.A ");
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);
assertTrue(pn instanceof SendPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopPlanNode);
assertEquals(JoinType.LEFT, ((NestLoopPlanNode) nlpn).getJoinType());
pn = nlpn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1");
pn = nlpn.getChild(1);
checkSeqScan(pn, "T1");
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P2");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
// Using index scan for group by only: use serial aggregate instead hash aggregate
assertNotNull(pn.getInlinePlanNode(PlanNodeType.AGGREGATE));
// Right outer join
planNodes = compileToFragments("SELECT R1.A, R1.C FROM R1 RIGHT JOIN (SELECT A, count(*) C FROM P1 GROUP BY A) T1 ON T1.C = R1.C ");
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);
assertTrue(pn instanceof SendPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopPlanNode);
assertEquals(JoinType.LEFT, ((NestLoopPlanNode) nlpn).getJoinType());
pn = nlpn.getChild(1);
checkSeqScan(pn, "R1", "A", "C");
pn = nlpn.getChild(0);
checkSeqScan(pn, "T1", "C");
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1", "A", "C");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
// Using index scan for group by only: use serial aggregate instead hash aggregate
assertNotNull(pn.getInlinePlanNode(PlanNodeType.AGGREGATE));
// RIGHT partition table
planNodes = compileToFragments("SELECT T1.CC FROM P1 RIGHT JOIN (SELECT A, count(*) CC FROM P2 GROUP BY A) T1 ON T1.A = P1.A ");
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);
assertTrue(pn instanceof SendPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopIndexPlanNode);
assertEquals(JoinType.LEFT, ((NestLoopIndexPlanNode) nlpn).getJoinType());
pn = nlpn.getInlinePlanNode(PlanNodeType.INDEXSCAN);
checkPrimaryKeyIndexScan(pn, "P1");
pn = nlpn.getChild(0);
checkSeqScan(pn, "T1");
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P2");
assertNotNull(pn.getInlinePlanNode(PlanNodeType.PROJECTION));
// Using index scan for group by only: use serial aggregate instead hash aggregate
assertNotNull(pn.getInlinePlanNode(PlanNodeType.AGGREGATE));
// Join locally: inner join case for subselects
sql = "SELECT R1.A, R1.C FROM R1 INNER JOIN (SELECT A, C FROM P1) T1 ON T1.C = R1.C ";
sqlNoSimplification = "SELECT R1.A, R1.C FROM R1 INNER JOIN (SELECT DISTINCT A, C FROM P1) T1 ON T1.C = R1.C ";
equivalentSql = "SELECT R1.A, R1.C FROM R1 INNER JOIN P1 T1 ON T1.C = R1.C ";
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);
assertTrue(pn instanceof SendPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopPlanNode);
assertEquals(JoinType.INNER, ((NestLoopPlanNode) nlpn).getJoinType());
pn = nlpn.getChild(0);
checkSeqScan(pn, "R1", "A", "C");
pn = nlpn.getChild(1);
checkSeqScan(pn, "T1", "C");
checkSubquerySimplification(sql, equivalentSql);
// Two sub-queries. One is partitioned and the other one is replicated
sql = "select A, AC FROM (SELECT A FROM R1) T1, (SELECT C AC FROM P1) T2 WHERE T1.A = T2.AC ";
sqlNoSimplification = "select A, AC FROM (SELECT A FROM R1 LIMIT 10) T1, (SELECT DISTINCT A AC FROM P1) T2 WHERE T1.A = T2.AC ";
equivalentSql = "select T1.A, T2.C AC FROM R1 T1, P1 T2 WHERE T1.A = T2.C ";
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);
assertTrue(pn instanceof SendPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopPlanNode);
assertEquals(JoinType.INNER, ((NestLoopPlanNode) nlpn).getJoinType());
pn = nlpn.getChild(0);
checkSeqScan(pn, "T1", "A");
pn = pn.getChild(0);
checkSeqScan(pn, "R1", "A");
pn = nlpn.getChild(1);
checkSeqScan(pn, "T2", "AC");
checkSubquerySimplification(sql, equivalentSql);
// This is a single fragment plan because planner can detect "A = 3".
// Join locally
sql = "select A1, A2 FROM (SELECT A A1 FROM R1) T1, (SELECT A A2 FROM P1 where A = 3) T2 WHERE T1.A1 = T2.A2 ";
sqlNoSimplification = "select A2, A1 FROM (SELECT DISTINCT A A1 FROM R1) T1, (SELECT DISTINCT A A2 FROM P1 where A = 3) T2 WHERE T1.A1 = T2.A2 ";
equivalentSql = "select T1.A A1, T2.A A2 FROM R1 T1 join P1 T2 on T2.A = 3 and T1.A = T2.A";
planNodes = compileToFragments(sqlNoSimplification);
assertEquals(1, planNodes.size());
pn = planNodes.get(0);
assertTrue(pn instanceof SendPlanNode);
pn = pn.getChild(0);
assertTrue(pn instanceof ProjectionPlanNode);
nlpn = pn.getChild(0);
assertTrue(nlpn instanceof NestLoopPlanNode);
pn = nlpn.getChild(0);
checkSeqScan(pn, "T1", "A1");
pn = nlpn.getChild(1);
checkSeqScan(pn, "T2", "A2");
pn = pn.getChild(0);
checkPrimaryKeyIndexScan(pn, "P1", "A");
assertEquals(2, ((IndexScanPlanNode) pn).getInlinePlanNodes().size());
assertNotNull(((IndexScanPlanNode) pn).getInlinePlanNode(PlanNodeType.PROJECTION));
assertNotNull(((IndexScanPlanNode) pn).getInlinePlanNode(PlanNodeType.AGGREGATE));
checkSubquerySimplification(sql, equivalentSql);
// More single partition detection
planNodes = compileToFragments("select C FROM (SELECT P1.C FROM P1, P2 " + "WHERE P1.A = P2.A AND P1.A = 3) T1 ");
assertEquals(1, planNodes.size());
planNodes = compileToFragments("select T1.C FROM (SELECT P1.C FROM P1, P2 " + "WHERE P1.A = P2.A AND P1.A = 3) T1, R1 where T1.C > R1.C ");
assertEquals(1, planNodes.size());
planNodes = compileToFragments("select T1.C FROM (SELECT P1.C FROM P1, P2 " + "WHERE P1.A = P2.A AND P1.A = 3) T1, (select C FROM R1) T2 where T1.C > T2.C ");
assertEquals(1, planNodes.size());
}
Aggregations