Search in sources :

Example 6 with AbstractPlanNode

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

the class InlineOrderByIntoMergeReceive method applyOptimization.

/**
     * Convert ReceivePlanNodes into MergeReceivePlanNodes when the
     * RECEIVE node's nearest parent is a window function.  We won't
     * have any inline limits or aggregates here, so this is somewhat
     * simpler than the order by case.
     *
     * @param plan
     * @return
     */
private AbstractPlanNode applyOptimization(WindowFunctionPlanNode plan) {
    assert (plan.getChildCount() == 1);
    assert (plan.getChild(0) != null);
    AbstractPlanNode child = plan.getChild(0);
    assert (child != null);
    // an order by node.
    if (!(child instanceof OrderByPlanNode)) {
        return plan;
    }
    OrderByPlanNode onode = (OrderByPlanNode) child;
    child = onode.getChild(0);
    // for this optimization to work.
    if (!(child instanceof ReceivePlanNode)) {
        return plan;
    }
    ReceivePlanNode receiveNode = (ReceivePlanNode) child;
    assert (receiveNode.getChildCount() == 1);
    child = receiveNode.getChild(0);
    // The Receive node needs a send node child.
    assert (child instanceof SendPlanNode);
    SendPlanNode sendNode = (SendPlanNode) child;
    child = sendNode.getChild(0);
    // returns the number in the plan node.
    if (!(child instanceof IndexSortablePlanNode)) {
        return plan;
    }
    IndexSortablePlanNode indexed = (IndexSortablePlanNode) child;
    if (indexed.indexUse().getWindowFunctionUsesIndex() != 0) {
        return plan;
    }
    // Remove the Receive node and the Order by node
    // and replace them with a MergeReceive node.  Leave
    // the order by node inline in the MergeReceive node,
    // since we need it to calculate the merge.
    plan.clearChildren();
    receiveNode.removeFromGraph();
    MergeReceivePlanNode mrnode = new MergeReceivePlanNode();
    mrnode.addInlinePlanNode(onode);
    mrnode.addAndLinkChild(sendNode);
    plan.addAndLinkChild(mrnode);
    return plan;
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) IndexSortablePlanNode(org.voltdb.plannodes.IndexSortablePlanNode) OrderByPlanNode(org.voltdb.plannodes.OrderByPlanNode) SendPlanNode(org.voltdb.plannodes.SendPlanNode) ReceivePlanNode(org.voltdb.plannodes.ReceivePlanNode) MergeReceivePlanNode(org.voltdb.plannodes.MergeReceivePlanNode) MergeReceivePlanNode(org.voltdb.plannodes.MergeReceivePlanNode)

Example 7 with AbstractPlanNode

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

the class WriterSubPlanAssembler method nextPlan.

/**
     * Pull a join order out of the join orders deque, compute all possible plans
     * for that join order, then append them to the computed plans deque.
     */
@Override
AbstractPlanNode nextPlan() {
    if (!m_generatedPlans) {
        assert (m_parsedStmt.m_joinTree != null);
        // Clone the node to make make sure that analyze expression is called
        // only once on the node.
        JoinNode tableNode = (JoinNode) m_parsedStmt.m_joinTree.clone();
        // Analyze join conditions
        tableNode.analyzeJoinExpressions(m_parsedStmt.m_noTableSelectionList);
        // these just shouldn't happen right?
        assert (m_parsedStmt.m_noTableSelectionList.size() == 0);
        m_generatedPlans = true;
        // This is either UPDATE or DELETE statement. Consolidate all expressions
        // into the WHERE list.
        tableNode.m_whereInnerList.addAll(tableNode.m_joinInnerList);
        tableNode.m_joinInnerList.clear();
        tableNode.m_accessPaths.addAll(getRelevantAccessPathsForTable(tableNode.getTableScan(), null, tableNode.m_whereInnerList, null));
        for (AccessPath path : tableNode.m_accessPaths) {
            tableNode.m_currentAccessPath = path;
            AbstractPlanNode plan = getAccessPlanForTable(tableNode);
            m_plans.add(plan);
        }
    }
    return m_plans.poll();
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) JoinNode(org.voltdb.planner.parseinfo.JoinNode)

Example 8 with AbstractPlanNode

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

the class PushdownLimits method recursivelyApply.

@Override
protected AbstractPlanNode recursivelyApply(AbstractPlanNode plan) {
    assert (plan != null);
    // depth first:
    //     find LimitPlanNodes with exactly one child
    //     where that child is an AbstractScanPlanNode
    //     disconnect the LimitPlanNode
    //     and inline the LimitPlanNode in to the AbstractScanPlanNode
    ArrayList<AbstractPlanNode> children = new ArrayList<AbstractPlanNode>();
    for (int i = 0; i < plan.getChildCount(); i++) children.add(plan.getChild(i));
    plan.clearChildren();
    for (AbstractPlanNode child : children) {
        // TODO this will break when children feed multiple parents
        child = recursivelyApply(child);
        child.clearParents();
        plan.addAndLinkChild(child);
    }
    if (!(plan instanceof LimitPlanNode)) {
        return plan;
    }
    if (plan.getChildCount() != 1) {
        assert (plan.getChildCount() == 1);
        return plan;
    }
    AbstractPlanNode child = plan.getChild(0);
    // push into Scans
    if (child instanceof AbstractScanPlanNode) {
        // in future, this limit can be aggregate inline node.
        if (AggregatePlanNode.getInlineAggregationNode(child) != null) {
            return plan;
        }
        plan.clearChildren();
        child.clearParents();
        child.addInlinePlanNode(plan);
        return child;
    }
    // == child/projection . recursivelyApply(plan/limit . leaf/whatever)
    if (child instanceof ProjectionPlanNode) {
        assert (child.getChildCount() == 1);
        AbstractPlanNode leaf = child.getChild(0);
        leaf.clearParents();
        plan.clearChildren();
        plan.addAndLinkChild(leaf);
        child.clearChildren();
        child.clearParents();
        child.addAndLinkChild(plan);
        return recursivelyApply(child);
    }
    // push into JOINs
    if (child instanceof AbstractJoinPlanNode) {
        plan.clearChildren();
        child.clearParents();
        child.addInlinePlanNode(plan);
        // }
        return child;
    }
    return plan;
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) AbstractScanPlanNode(org.voltdb.plannodes.AbstractScanPlanNode) AbstractJoinPlanNode(org.voltdb.plannodes.AbstractJoinPlanNode) ArrayList(java.util.ArrayList) LimitPlanNode(org.voltdb.plannodes.LimitPlanNode) ProjectionPlanNode(org.voltdb.plannodes.ProjectionPlanNode)

Example 9 with AbstractPlanNode

use of org.voltdb.plannodes.AbstractPlanNode 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 10 with AbstractPlanNode

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

the class TestPlansGroupBy method testDistinctA1_Subquery.

public void testDistinctA1_Subquery() {
    AbstractPlanNode p;
    List<AbstractPlanNode> pns;
    // Distinct rewrote with group by
    pns = compileToFragments("select * from (SELECT DISTINCT A1 FROM T1) temp");
    p = pns.get(0).getChild(0);
    assertTrue(p instanceof SeqScanPlanNode);
    assertTrue(p.getChild(0) instanceof HashAggregatePlanNode);
    assertTrue(p.getChild(0).getChild(0) instanceof ReceivePlanNode);
    p = pns.get(1).getChild(0);
    assertTrue(p instanceof AbstractScanPlanNode);
    assertNotNull(p.getInlinePlanNode(PlanNodeType.HASHAGGREGATE));
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) SeqScanPlanNode(org.voltdb.plannodes.SeqScanPlanNode) AbstractScanPlanNode(org.voltdb.plannodes.AbstractScanPlanNode) ReceivePlanNode(org.voltdb.plannodes.ReceivePlanNode) AbstractReceivePlanNode(org.voltdb.plannodes.AbstractReceivePlanNode) HashAggregatePlanNode(org.voltdb.plannodes.HashAggregatePlanNode)

Aggregations

AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)259 AbstractExpression (org.voltdb.expressions.AbstractExpression)55 IndexScanPlanNode (org.voltdb.plannodes.IndexScanPlanNode)48 ProjectionPlanNode (org.voltdb.plannodes.ProjectionPlanNode)48 AbstractScanPlanNode (org.voltdb.plannodes.AbstractScanPlanNode)46 SeqScanPlanNode (org.voltdb.plannodes.SeqScanPlanNode)44 AggregatePlanNode (org.voltdb.plannodes.AggregatePlanNode)37 NestLoopPlanNode (org.voltdb.plannodes.NestLoopPlanNode)37 HashAggregatePlanNode (org.voltdb.plannodes.HashAggregatePlanNode)29 OrderByPlanNode (org.voltdb.plannodes.OrderByPlanNode)29 ReceivePlanNode (org.voltdb.plannodes.ReceivePlanNode)27 SendPlanNode (org.voltdb.plannodes.SendPlanNode)27 MergeReceivePlanNode (org.voltdb.plannodes.MergeReceivePlanNode)20 AbstractReceivePlanNode (org.voltdb.plannodes.AbstractReceivePlanNode)16 NestLoopIndexPlanNode (org.voltdb.plannodes.NestLoopIndexPlanNode)16 SchemaColumn (org.voltdb.plannodes.SchemaColumn)15 NodeSchema (org.voltdb.plannodes.NodeSchema)14 UnionPlanNode (org.voltdb.plannodes.UnionPlanNode)14 LimitPlanNode (org.voltdb.plannodes.LimitPlanNode)12 PlanNodeType (org.voltdb.types.PlanNodeType)12