Package org.voltdb.planner

Source Code of org.voltdb.planner.CompiledPlan

/* This file is part of VoltDB.
* Copyright (C) 2008-2014 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.voltdb.planner;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

import org.voltdb.ParameterSet;
import org.voltdb.VoltType;
import org.voltdb.common.Constants;
import org.voltdb.expressions.AbstractExpression;
import org.voltdb.expressions.ParameterValueExpression;
import org.voltdb.plannodes.AbstractPlanNode;
import org.voltdb.plannodes.IndexCountPlanNode;
import org.voltdb.plannodes.IndexScanPlanNode;
import org.voltdb.plannodes.PlanNodeList;
import org.voltdb.types.PlanNodeType;

/**
* A triple-tuple to hold a complete plan graph along with its
* input (parameters) and output (result columns). This class just
* exists to make it a convenient return value for methods that
* output plans.
*
*/
public class CompiledPlan {

    public final static int MAX_PARAM_COUNT = 1025; // keep synched with value in EE VoltDBEngine.h

    /** A complete plan graph for SP plans and the top part of MP plans */
    public AbstractPlanNode rootPlanGraph;

    /** A "collector" fragment for two-part MP plans */
    public AbstractPlanNode subPlanGraph;

    /**
     * The SQL text of the statement
     */
    public String sql = null;

    /**
     * Cost of the plan as estimated (not necessarily well)
     * by the planner
     */
    public double cost = 0.0;

    /**
     * The textual explanation of aggregation, join order and
     * access path selection.
     */
    public String explainedPlan = null;

    /** Parameters and their types in parameter index order */
    public ParameterValueExpression[] parameters = null;
    private VoltType[] m_parameterTypes = null;

    /** Parameter values, if the planner pulled constants out of the plan */
    private ParameterSet m_extractedParamValues = ParameterSet.emptyParameterSet();

    /**
     * If true, divide the number of tuples changed
     * by the number of partitions, as the number will
     * be the sum of tuples changed on all replicas.
     */
    public boolean replicatedTableDML = false;

    /** Does the statement write? */
    private boolean m_readOnly = false;

    /**
     * Whether the plan's statement mandates a result with nondeterministic content;
     */
    private boolean m_statementHasLimitOrOffset = false;

    /**
     * Whether the plan's statement mandates a result with deterministic content and order;
     */
    private boolean m_statementIsOrderDeterministic = false;

    /** Which extracted param is the partitioning object (assuming parameterized plans) */
    public int partitioningKeyIndex = -1;

    private Object m_partitioningValue;

    void resetPlanNodeIds() {
        int nextId = resetPlanNodeIds(rootPlanGraph, 1);
        if (subPlanGraph != null) {
            resetPlanNodeIds(subPlanGraph, nextId);
        }
    }

    private int resetPlanNodeIds(AbstractPlanNode node, int nextId) {
        node.overrideId(nextId++);
        for (AbstractPlanNode inNode : node.getInlinePlanNodes().values()) {
            inNode.overrideId(0);
        }

        for (int i = 0; i < node.getChildCount(); i++) {
            AbstractPlanNode child = node.getChild(i);
            assert(child != null);
            nextId = resetPlanNodeIds(child, nextId);
        }

        return nextId;
    }

    /**
     * Mark the level of result determinism imposed by the statement,
     * which can save us from a difficult determination based on the plan graph.
     */
    public void statementGuaranteesDeterminism(boolean hasLimitOrOffset, boolean order) {
        m_statementHasLimitOrOffset = hasLimitOrOffset;
        m_statementIsOrderDeterministic = order;
    }

    /**
     * Accessor for flag marking the plan as guaranteeing an identical result/effect
     * when "replayed" against the same database state, such as during replication or CL recovery.
     * @return the corresponding value from the first fragment
     */
    public boolean isOrderDeterministic() {
        if (m_statementIsOrderDeterministic) {
            return true;
        }
        return rootPlanGraph.isOrderDeterministic();
    }

    /**
     * Accessor for flag marking the original statement as guaranteeing an identical result/effect
     * when "replayed" against the same database state, such as during replication or CL recovery.
     */
    public boolean hasDeterministicStatement()
    {
        return m_statementIsOrderDeterministic;
    }

    /**
     * Accessor for flag marking the plan as guaranteeing an identical result/effect
     * when "replayed" against the same database state, such as during replication or CL recovery.
     * @return the corresponding value from the first fragment
     */
    public boolean hasLimitOrOffset() {
        return m_statementHasLimitOrOffset;
    }

    /**
     * Accessor for description of plan non-determinism.
     * @return the corresponding value from the first fragment
     */
    public String nondeterminismDetail() {
        return rootPlanGraph.nondeterminismDetail();
    }

    public int countSeqScans() {
        int total = rootPlanGraph.findAllNodesOfType(PlanNodeType.SEQSCAN).size();
        if (subPlanGraph != null) {
            total += subPlanGraph.findAllNodesOfType(PlanNodeType.SEQSCAN).size();
        }
        // add full index scans
        ArrayList<AbstractPlanNode> indexScanNodes = rootPlanGraph.findAllNodesOfType(PlanNodeType.INDEXSCAN);
        if (subPlanGraph != null) {
            indexScanNodes.addAll(subPlanGraph.findAllNodesOfType(PlanNodeType.INDEXSCAN));
        }
        for (AbstractPlanNode node : indexScanNodes) {
            if (((IndexScanPlanNode)node).getSearchKeyExpressions().isEmpty()) {
                total++;
            }
        }
        return total;
    }

    public void setPartitioningValue(Object object) {
        m_partitioningValue = object;
    }

    public Object getPartitioningValue() {
        return m_partitioningValue;
    }

    public static byte[] bytesForPlan(AbstractPlanNode planGraph) {
        if (planGraph == null) {
            return null;
        }

        PlanNodeList planList = new PlanNodeList(planGraph);
        return planList.toJSONString().getBytes(Constants.UTF8ENCODING);
    }

    // A reusable step extracted from boundParamIndexes so it can be applied to two different
    // sources of bindings, IndexScans and IndexCounts.
    private static void setParamIndexes(BitSet ints, List<AbstractExpression> params) {
        for(AbstractExpression ae : params) {
            assert(ae instanceof ParameterValueExpression);
            ParameterValueExpression pve = (ParameterValueExpression) ae;
            int param = pve.getParameterIndex();
            ints.set(param);
        }
    }

    // An obvious but apparently missing BitSet utility function
    // to convert the set bits to their integer indexes.
    private static int[] bitSetToIntVector(BitSet ints) {
        int intCount = ints.cardinality();
        if (intCount == 0) {
            return null;
        }
        int[] result = new int[intCount];
        int nextBit = ints.nextSetBit(0);
        for (int ii = 0; ii < intCount; ii++) {
            assert(nextBit != -1);
            result[ii] = nextBit;
            nextBit = ints.nextSetBit(nextBit+1);
        }
        assert(nextBit == -1);
        return result;
    }

    /// Extract a sorted de-duped vector of all the bound parameter indexes in a plan. Or null if none.
    public int[] boundParamIndexes() {
        if (parameters.length == 0) {
            return null;
        }

        BitSet ints = new BitSet();
        ArrayList<AbstractPlanNode> ixscans = rootPlanGraph.findAllNodesOfType(PlanNodeType.INDEXSCAN);
        if (subPlanGraph != null) {
            ixscans.addAll(subPlanGraph.findAllNodesOfType(PlanNodeType.INDEXSCAN));
        }
        for (AbstractPlanNode apn : ixscans) {
            assert(apn instanceof IndexScanPlanNode);
            IndexScanPlanNode ixs = (IndexScanPlanNode) apn;
            setParamIndexes(ints, ixs.getBindings());
        }

        ArrayList<AbstractPlanNode> ixcounts = rootPlanGraph.findAllNodesOfType(PlanNodeType.INDEXCOUNT);
        if (subPlanGraph != null) {
            ixcounts.addAll(subPlanGraph.findAllNodesOfType(PlanNodeType.INDEXCOUNT));
        }
        for (AbstractPlanNode apn : ixcounts) {
            assert(apn instanceof IndexCountPlanNode);
            IndexCountPlanNode ixc = (IndexCountPlanNode) apn;
            setParamIndexes(ints, ixc.getBindings());
        }
        return bitSetToIntVector(ints);
    }

    // This is assumed to be called only after parameters has been fully initialized.
    public VoltType[] parameterTypes() {
        if (m_parameterTypes == null) {
            m_parameterTypes = new VoltType[parameters.length];
            int ii = 0;
            for (ParameterValueExpression param : parameters) {
                m_parameterTypes[ii++] = param.getValueType();
            }
        }
        return m_parameterTypes;
    }

    public boolean extractParamValues(ParameterizationInfo paramzInfo) throws Exception {
        VoltType[] paramTypes = parameterTypes();
        if (paramTypes.length > MAX_PARAM_COUNT) {
            return false;
        }
        m_extractedParamValues = paramzInfo.extractedParamValues(paramTypes);
        return true;
    }

    public ParameterSet extractedParamValues() {
        return m_extractedParamValues;
    }

    public boolean getReadOnly() {
        return m_readOnly;
    }

    public void setReadOnly(boolean newValue) {
        m_readOnly = newValue;
    }
}
TOP

Related Classes of org.voltdb.planner.CompiledPlan

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.