Package edu.brown.optimizer.optimizations

Source Code of edu.brown.optimizer.optimizations.LimitPushdownOptimization

package edu.brown.optimizer.optimizations;

import java.util.Collection;

import org.apache.log4j.Logger;
import org.voltdb.plannodes.AbstractJoinPlanNode;
import org.voltdb.plannodes.AbstractPlanNode;
import org.voltdb.plannodes.AbstractScanPlanNode;
import org.voltdb.plannodes.LimitPlanNode;
import org.voltdb.plannodes.OrderByPlanNode;
import org.voltdb.plannodes.ReceivePlanNode;
import org.voltdb.plannodes.SendPlanNode;
import org.voltdb.utils.Pair;

import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.optimizer.PlanOptimizerState;
import edu.brown.plannodes.PlanNodeUtil;
import edu.brown.utils.CollectionUtil;

/**
* Pushdown a LIMIT before we send data over the network
* @author pavlo
*/
public class LimitPushdownOptimization extends AbstractOptimization {
    private static final Logger LOG = Logger.getLogger(LimitPushdownOptimization.class);
    private static final LoggerBoolean debug = new LoggerBoolean();

    public LimitPushdownOptimization(PlanOptimizerState state) {
        super(state);
    }

    @Override
    public Pair<Boolean, AbstractPlanNode> optimize(final AbstractPlanNode root) {
        // Check whether this PlanTree contains a LimitPlanNode
        // If it does and there are no joins, then we should be able to push duplicates
        // down into the ScanPlanNode so that we can prune out as much as we can before
        // we send it over the wire. This is a basic a Merge-Sort operation
        Collection<OrderByPlanNode> orderby_nodes = PlanNodeUtil.getPlanNodes(root, OrderByPlanNode.class);
        Collection<LimitPlanNode> limit_nodes = PlanNodeUtil.getPlanNodes(root, LimitPlanNode.class);
        Collection<AbstractJoinPlanNode> join_nodes = PlanNodeUtil.getPlanNodes(root, AbstractJoinPlanNode.class);
        Collection<ReceivePlanNode> recv_nodes = PlanNodeUtil.getPlanNodes(root, ReceivePlanNode.class);
        if (limit_nodes.size() != 1) {
            if (debug.val)
                LOG.debug("SKIP - Number of LimitPlanNodes is " + limit_nodes.size());
            return (Pair.of(false, root));
        }
        else if (join_nodes.isEmpty() == false) {
            if (debug.val)
                LOG.debug("SKIP - Contains a JoinPlanNode " + join_nodes);
            return (Pair.of(false, root));
        }
        else if (recv_nodes.isEmpty()) {
            if (debug.val)
                LOG.debug("SKIP - Does not contain any ReceivePlanNodes");
            return (Pair.of(false, root));
        }

        OrderByPlanNode orderby_node = null;
        LimitPlanNode limit_node = null;
       
        try {
            // If there is an OrderByPlanNode, then that we need to clone that too.
            if (orderby_nodes.size() != 0) {
                orderby_node = (OrderByPlanNode) CollectionUtil.first(orderby_nodes).clone(false, true);
                assert (orderby_node != null);
            }
            limit_node = (LimitPlanNode) CollectionUtil.first(limit_nodes).clone(false, true);
        } catch (CloneNotSupportedException ex) {
            throw new RuntimeException(ex);
        }
        assert (limit_node != null);

        if (debug.val) {
            LOG.debug("LIMIT:    " + PlanNodeUtil.debug(limit_node));
            LOG.debug("ORDER BY: " + PlanNodeUtil.debug(orderby_node));
            LOG.debug(PlanNodeUtil.getPlanNodes(root, AbstractScanPlanNode.class));
        }
        AbstractScanPlanNode scan_node = CollectionUtil.first(PlanNodeUtil.getPlanNodes(root, AbstractScanPlanNode.class));
        assert (scan_node != null) : "Unexpected PlanTree:\n" + PlanNodeUtil.debug(root);
        SendPlanNode send_node = (SendPlanNode) scan_node.getParent(0);
        assert (send_node != null);

        send_node.addIntermediary(limit_node);
        if (orderby_node != null) {
            limit_node.addIntermediary(orderby_node);
            // Need to make sure that the LIMIT has the proper output columns
            limit_node.setOutputColumns(orderby_node.getOutputColumnGUIDs());
            state.markDirty(orderby_node);
        } else {
            // Need to make sure that the LIMIT has the proper output columns
            limit_node.setOutputColumns(scan_node.getOutputColumnGUIDs());
        }
        state.markDirty(limit_node);
        if (debug.val)
            LOG.debug("PLANOPT - Added " + limit_node + " after " + scan_node);

        return (Pair.of(true, root));
    }

}
TOP

Related Classes of edu.brown.optimizer.optimizations.LimitPushdownOptimization

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.