Search in sources :

Example 26 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode in project voltdb by VoltDB.

the class TestPlansGroupBy method checkMVReaggregateFeatureMergeReceive.

// topNode, reAggNode
private void checkMVReaggregateFeatureMergeReceive(List<AbstractPlanNode> pns, boolean needFix, int numGroupByOfReaggNode, int numAggsOfReaggNode, boolean aggPushdown, boolean aggInline, SortDirectionType sortDirection) {
    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);
    }
    AbstractPlanNode receiveNode = p;
    assertNotNull(receiveNode);
    AggregatePlanNode reAggNode = AggregatePlanNode.getInlineAggregationNode(receiveNode);
    if (needFix) {
        assertNotNull(reAggNode);
        assertEquals(numGroupByOfReaggNode, reAggNode.getGroupByExpressionsSize());
        assertEquals(numAggsOfReaggNode, reAggNode.getAggregateTypesSize());
    } else {
        assertNull(reAggNode);
    }
    p = pns.get(1);
    assertTrue(p instanceof SendPlanNode);
    p = p.getChild(0);
    assertTrue(p instanceof IndexScanPlanNode);
    assertEquals(sortDirection, ((IndexScanPlanNode) p).getSortDirection());
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) HashAggregatePlanNode(org.voltdb.plannodes.HashAggregatePlanNode) AggregatePlanNode(org.voltdb.plannodes.AggregatePlanNode) SendPlanNode(org.voltdb.plannodes.SendPlanNode) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) ProjectionPlanNode(org.voltdb.plannodes.ProjectionPlanNode)

Example 27 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode in project voltdb by VoltDB.

the class TestPlansJoin method perJoinOpTestBasicIndexOuterJoin.

private void perJoinOpTestBasicIndexOuterJoin(JoinOp joinOp) {
    // R3 is indexed but it's the outer table and the join expression
    // must stay at the NLJ so the index can't be used
    String query;
    AbstractPlanNode pn;
    AbstractPlanNode node;
    NestLoopIndexPlanNode nlij;
    NestLoopPlanNode nlj;
    SeqScanPlanNode seqScan;
    IndexScanPlanNode indexScan;
    AbstractExpression predicate;
    query = "SELECT * FROM R3 LEFT JOIN R2 ON R3.A" + joinOp + "R2.C";
    pn = compileToTopDownTree(query, 4, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOP, PlanNodeType.SEQSCAN, PlanNodeType.SEQSCAN);
    node = followAssertedLeftChain(pn, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOP);
    nlj = (NestLoopPlanNode) node;
    assertEquals(JoinType.LEFT, nlj.getJoinType());
    assertNull(nlj.getPreJoinPredicate());
    predicate = nlj.getJoinPredicate();
    assertExprTopDownTree(predicate, joinOp.toOperator(), ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_TUPLE);
    assertNull(nlj.getWherePredicate());
    seqScan = (SeqScanPlanNode) nlj.getChild(0);
    assertEquals("R3", seqScan.getTargetTableName());
    seqScan = (SeqScanPlanNode) nlj.getChild(1);
    assertEquals("R2", seqScan.getTargetTableName());
    // R3 is indexed but it's the outer table so index can't be used
    query = "SELECT * FROM R2 RIGHT JOIN R3 ON R3.A" + joinOp + "R2.C";
    pn = compileToTopDownTree(query, 4, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOP, PlanNodeType.SEQSCAN, PlanNodeType.SEQSCAN);
    node = followAssertedLeftChain(pn, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOP);
    nlj = (NestLoopPlanNode) node;
    assertEquals(JoinType.LEFT, nlj.getJoinType());
    assertNull(nlj.getPreJoinPredicate());
    predicate = nlj.getJoinPredicate();
    assertExprTopDownTree(predicate, joinOp.toOperator(), ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_TUPLE);
    assertNull(nlj.getWherePredicate());
    seqScan = (SeqScanPlanNode) nlj.getChild(0);
    assertEquals("R3", seqScan.getTargetTableName());
    seqScan = (SeqScanPlanNode) nlj.getChild(1);
    assertEquals("R2", seqScan.getTargetTableName());
    if (joinOp != JoinOp.EQUAL) {
        // weaken test for now
        return;
    }
    query = "SELECT * FROM R2 LEFT JOIN R3 ON R2.C" + joinOp + "R3.A";
    pn = compileToTopDownTree(query, 4, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOPINDEX, PlanNodeType.SEQSCAN);
    node = followAssertedLeftChain(pn, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOPINDEX);
    nlij = (NestLoopIndexPlanNode) node;
    assertEquals(JoinType.LEFT, nlij.getJoinType());
    seqScan = (SeqScanPlanNode) nlij.getChild(0);
    assertEquals("R2", seqScan.getTargetTableName());
    indexScan = nlij.getInlineIndexScan();
    assertEquals(IndexLookupType.EQ, indexScan.getLookupType());
    predicate = indexScan.getEndExpression();
    assertExprTopDownTree(predicate, joinOp.toOperator(), ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_TUPLE);
    assertNull(indexScan.getPredicate());
    assertEquals("R3", indexScan.getTargetTableName());
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) SeqScanPlanNode(org.voltdb.plannodes.SeqScanPlanNode) AbstractExpression(org.voltdb.expressions.AbstractExpression) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) NestLoopPlanNode(org.voltdb.plannodes.NestLoopPlanNode) NestLoopIndexPlanNode(org.voltdb.plannodes.NestLoopIndexPlanNode)

Example 28 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode 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);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) TupleValueExpression(org.voltdb.expressions.TupleValueExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) OrderByPlanNode(org.voltdb.plannodes.OrderByPlanNode) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) ConstantValueExpression(org.voltdb.expressions.ConstantValueExpression) NestLoopIndexPlanNode(org.voltdb.plannodes.NestLoopIndexPlanNode) ProjectionPlanNode(org.voltdb.plannodes.ProjectionPlanNode)

Example 29 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode 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());
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) SendPlanNode(org.voltdb.plannodes.SendPlanNode) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) MergeReceivePlanNode(org.voltdb.plannodes.MergeReceivePlanNode) ReceivePlanNode(org.voltdb.plannodes.ReceivePlanNode) NestLoopPlanNode(org.voltdb.plannodes.NestLoopPlanNode) ProjectionPlanNode(org.voltdb.plannodes.ProjectionPlanNode) NestLoopIndexPlanNode(org.voltdb.plannodes.NestLoopIndexPlanNode)

Example 30 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode in project voltdb by VoltDB.

the class TestPlansSubQueries method testExpressionSubqueryWithIndexScan.

/**
     * Expression subquery currently is not optimized to use any index. But this does not prevent the
     * parent query to use index for other purposes.
     */
public void testExpressionSubqueryWithIndexScan() {
    AbstractPlanNode pn;
    String sql;
    // INDEX on A, for sort order only
    sql = "SELECT A FROM R4 where A in (select A from R4 where A > 3) order by A;";
    pn = compile(sql);
    pn = pn.getChild(0);
    assertTrue(pn instanceof IndexScanPlanNode);
    assertEquals(0, ((IndexScanPlanNode) pn).getSearchKeyExpressions().size());
    assertNotNull(((IndexScanPlanNode) pn).getPredicate());
    // INDEX on A, uniquely match A = 4,
    sql = "SELECT A FROM R4 where A = 4 and C in (select A from R4 where A > 3);";
    pn = compile(sql);
    pn = pn.getChild(0);
    assertTrue(pn instanceof IndexScanPlanNode);
    assertEquals(1, ((IndexScanPlanNode) pn).getSearchKeyExpressions().size());
    AbstractExpression comp = ((IndexScanPlanNode) pn).getSearchKeyExpressions().get(0);
    assertEquals(ExpressionType.VALUE_CONSTANT, comp.getExpressionType());
    assertEquals("4", ((ConstantValueExpression) comp).getValue());
    assertNotNull(((IndexScanPlanNode) pn).getPredicate());
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) AbstractExpression(org.voltdb.expressions.AbstractExpression) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode)

Aggregations

IndexScanPlanNode (org.voltdb.plannodes.IndexScanPlanNode)60 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)48 AbstractExpression (org.voltdb.expressions.AbstractExpression)22 NestLoopIndexPlanNode (org.voltdb.plannodes.NestLoopIndexPlanNode)15 SeqScanPlanNode (org.voltdb.plannodes.SeqScanPlanNode)14 NestLoopPlanNode (org.voltdb.plannodes.NestLoopPlanNode)11 ProjectionPlanNode (org.voltdb.plannodes.ProjectionPlanNode)8 AggregatePlanNode (org.voltdb.plannodes.AggregatePlanNode)7 OrderByPlanNode (org.voltdb.plannodes.OrderByPlanNode)6 ArrayList (java.util.ArrayList)5 Index (org.voltdb.catalog.Index)5 ReceivePlanNode (org.voltdb.plannodes.ReceivePlanNode)5 AbstractReceivePlanNode (org.voltdb.plannodes.AbstractReceivePlanNode)4 AbstractScanPlanNode (org.voltdb.plannodes.AbstractScanPlanNode)4 HashAggregatePlanNode (org.voltdb.plannodes.HashAggregatePlanNode)4 SendPlanNode (org.voltdb.plannodes.SendPlanNode)4 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)3 IndexCountPlanNode (org.voltdb.plannodes.IndexCountPlanNode)3 StmtTableScan (org.voltdb.planner.parseinfo.StmtTableScan)2 AbstractJoinPlanNode (org.voltdb.plannodes.AbstractJoinPlanNode)2