/* 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.ArrayDeque;
import java.util.ArrayList;
import org.voltdb.catalog.Database;
import org.voltdb.catalog.Table;
import org.voltdb.plannodes.AbstractPlanNode;
/**
* For a delete or update plan, this class builds the part of the plan
* which collects tuples from relations. Given the tables and the predicate
* (and sometimes the output columns), this will build a plan that will output
* matching tuples to a temp table. A delete, update or send plan node can then
* be glued on top of it. In selects, aggregation and other projections are also
* done on top of the result from this class.
*
*/
public class WriterSubPlanAssembler extends SubPlanAssembler {
/** The only table involved in this update or delete stmt */
Table m_targetTable;
/** The list of generated plans. This allows generation in batches.*/
ArrayDeque<AbstractPlanNode> m_plans = new ArrayDeque<AbstractPlanNode>();
/** Only create access plans once - all are created in the first pass. */
boolean m_generatedPlans = false;
/**
*
* @param db The catalog's Database object.
* @param parsedStmt The parsed and dissected statement object describing the sql to execute.
* @param singlePartition Does this statement access one or multiple partitions?
*/
WriterSubPlanAssembler(PlannerContext context, Database db, AbstractParsedStmt parsedStmt,
boolean singlePartition, int partitionCount)
{
super(context, db, parsedStmt, singlePartition, partitionCount);
assert(m_parsedStmt.tableList.size() == 1);
m_targetTable = m_parsedStmt.tableList.get(0);
}
/**
* 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
protected AbstractPlanNode nextPlan() {
if (!m_generatedPlans) {
m_generatedPlans = true;
// for each table, just add the empty access path (the full table scan)
Table nextTables[] = new Table[0];
ArrayList<AccessPath> paths = getRelevantAccessPathsForTable(m_targetTable, nextTables);
// for each access path
for (AccessPath accessPath : paths) {
// get a plan
AbstractPlanNode scanPlan = getAccessPlanForTable(m_targetTable, accessPath);
m_plans.add(scanPlan);
}
}
return m_plans.poll();
}
/**
* Determines whether a table will require a distributed scan.
* @param table The table that may or may not require a distributed scan
* @return true if the table requires a distributed scan, false otherwise
*/
@Override
protected boolean tableRequiresDistributedScan(Table table) {
return m_singlePartition == false;
}
}