Search in sources :

Example 6 with OrderByPlanNode

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);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) UnionPlanNode(org.voltdb.plannodes.UnionPlanNode) OrderByPlanNode(org.voltdb.plannodes.OrderByPlanNode) ProjectionPlanNode(org.voltdb.plannodes.ProjectionPlanNode)

Example 7 with OrderByPlanNode

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());
    }
}
Also used : AbstractExpression(org.voltdb.expressions.AbstractExpression) OrderByPlanNode(org.voltdb.plannodes.OrderByPlanNode) SchemaColumn(org.voltdb.plannodes.SchemaColumn)

Example 8 with OrderByPlanNode

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());
        }
    }
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) OrderByPlanNode(org.voltdb.plannodes.OrderByPlanNode) HashAggregatePlanNode(org.voltdb.plannodes.HashAggregatePlanNode) AggregatePlanNode(org.voltdb.plannodes.AggregatePlanNode) SendPlanNode(org.voltdb.plannodes.SendPlanNode) HashAggregatePlanNode(org.voltdb.plannodes.HashAggregatePlanNode) LimitPlanNode(org.voltdb.plannodes.LimitPlanNode) MergeReceivePlanNode(org.voltdb.plannodes.MergeReceivePlanNode) ProjectionPlanNode(org.voltdb.plannodes.ProjectionPlanNode)

Example 9 with OrderByPlanNode

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);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) OrderByPlanNode(org.voltdb.plannodes.OrderByPlanNode) AbstractReceivePlanNode(org.voltdb.plannodes.AbstractReceivePlanNode) MergeReceivePlanNode(org.voltdb.plannodes.MergeReceivePlanNode) ReceivePlanNode(org.voltdb.plannodes.ReceivePlanNode) ProjectionPlanNode(org.voltdb.plannodes.ProjectionPlanNode)

Example 10 with OrderByPlanNode

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;
}
Also used : OrderByPlanNode(org.voltdb.plannodes.OrderByPlanNode)

Aggregations

OrderByPlanNode (org.voltdb.plannodes.OrderByPlanNode)32 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)29 ProjectionPlanNode (org.voltdb.plannodes.ProjectionPlanNode)25 SendPlanNode (org.voltdb.plannodes.SendPlanNode)9 AbstractExpression (org.voltdb.expressions.AbstractExpression)8 AggregatePlanNode (org.voltdb.plannodes.AggregatePlanNode)8 HashAggregatePlanNode (org.voltdb.plannodes.HashAggregatePlanNode)8 MergeReceivePlanNode (org.voltdb.plannodes.MergeReceivePlanNode)8 AbstractScanPlanNode (org.voltdb.plannodes.AbstractScanPlanNode)6 IndexScanPlanNode (org.voltdb.plannodes.IndexScanPlanNode)6 ReceivePlanNode (org.voltdb.plannodes.ReceivePlanNode)6 NestLoopPlanNode (org.voltdb.plannodes.NestLoopPlanNode)5 SeqScanPlanNode (org.voltdb.plannodes.SeqScanPlanNode)5 WindowFunctionPlanNode (org.voltdb.plannodes.WindowFunctionPlanNode)5 AbstractReceivePlanNode (org.voltdb.plannodes.AbstractReceivePlanNode)4 SchemaColumn (org.voltdb.plannodes.SchemaColumn)4 LimitPlanNode (org.voltdb.plannodes.LimitPlanNode)3 NodeSchema (org.voltdb.plannodes.NodeSchema)3 UnionPlanNode (org.voltdb.plannodes.UnionPlanNode)2 SortDirectionType (org.voltdb.types.SortDirectionType)2