/* This file is part of VoltDB.
* Copyright (C) 2008-2010 VoltDB L.L.C.
*
* VoltDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VoltDB 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.voltdb.expressions.AbstractExpression;
import org.voltdb.plannodes.AbstractPlanNode;
import edu.brown.plannodes.PlanNodeUtil;
/**
* 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 {
private static final Logger LOG = Logger.getLogger(CompiledPlan.class);
public static class Fragment implements Comparable<Fragment> {
/** A complete plan graph */
public AbstractPlanNode planGraph;
/** IDs of dependencies that must be met to begin */
public boolean hasDependencies = false;
/** Does this fragment get sent to all partitions */
public boolean multiPartition = false;
@Override
public int compareTo(Fragment o) {
Integer me = multiPartition == false ? 0 : 1;
Integer them = o.multiPartition == false ? 0 : 1;
return me.compareTo(them);
}
}
/**
* The set of plan fragments that make up this plan
* The first in the list must be the root.
*/
public List<Fragment> fragments = new ArrayList<Fragment>();
public String sql = null;
/** PAVLO: Full Plan JSON before Fragmentizer Gets to it! **/
public String fullplan_json = null;
/** A list of parameter names, indexes and types */
public List<ParameterInfo> parameters = new ArrayList<ParameterInfo>();
/** A list of output column ids, indexes and types */
public List<Integer> columns = new ArrayList<Integer>();
/**
* 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;
/**
* The tree representing the full where clause of the SQL
* statement that generated this plan. This is not used for
* execution, but is of interest to the database designer.
* Ultimately, this will end up serialized in the catalog.
* Note: this is not serialized when the parent CompiledPlan
* instance is serialized (only used for ad hoc sql).
*/
public AbstractExpression fullWhereClause = null;
/**
* The plangraph representing the full generated plan with
* the lowest cost for this sql statement. This is not used for
* execution, but is of interest to the database designer.
* Ultimately, this will end up serialized in the catalog.
* Note: this is not serialized when the parent CompiledPlan
* instance is serialized (only used for ad hoc sql).
*/
public AbstractPlanNode fullWinnerPlan = null;
public Set<Integer> getColumnGuids() {
Set<Integer> ret = new HashSet<Integer>();
// Output Columns
ret.addAll(columns);
for (Fragment frag : fragments) {
ret.addAll(PlanNodeUtil.getAllPlanColumnGuids(frag.planGraph));
} // FOR
return (ret);
}
public void freePlan(PlannerContext context, Set<Integer> skip) {
LOG.debug("Columns to Skip: " + skip);
for (Integer guid : columns) {
if (skip.contains(guid) == false) context.freeColumn(guid);
} // FOR
for (Fragment frag : fragments) {
if (skip.contains(frag) == false) frag.planGraph.freeColumns(skip);
} // FOR
}
void resetPlanNodeIds() {
int nextId = 1;
for (Fragment f : fragments)
nextId = resetPlanNodeIds(f.planGraph, nextId);
}
private int resetPlanNodeIds(AbstractPlanNode node, int nextId) {
node.overrideId(nextId++);
for (AbstractPlanNode inNode : node.getInlinePlanNodes().values()) {
inNode.overrideId(nextId++);
}
for (int i = 0; i < node.getChildPlanNodeCount(); i++) {
AbstractPlanNode child = node.getChild(i);
assert(child != null);
nextId = resetPlanNodeIds(child, nextId);
}
return nextId;
}
}