msg += " in a single-partition procedure.";
throw new PlanningErrorException(msg);
}
// the root of the insert plan is always an InsertPlanNode
InsertPlanNode insertNode = new InsertPlanNode(m_context, getNextPlanNodeId());
insertNode.setTargetTableName(targetTable.getTypeName());
insertNode.setMultiPartition(m_singlePartition == false);
// the materialize node creates a tuple to insert (which is frankly not
// always optimal)
MaterializePlanNode materializeNode =
new MaterializePlanNode(m_context, getNextPlanNodeId());
// get the ordered list of columns for the targettable using a helper
// function they're not guaranteed to be in order in the catalog
List<Column> columns =
CatalogUtil.getSortedCatalogItems(targetTable.getColumns(), "index");
// for each column in the table in order...
for (Column column : columns) {
// get the expression for the column
AbstractExpression expr = m_parsedInsert.columns.get(column);
// if there's no expression, make sure the column has
// some supported default value
if (expr == null) {
// if it's not nullable or defaulted we have a problem
if (column.getNullable() == false && column.getDefaulttype() == 0)
{
throw new PlanningErrorException("Column " + column.getName()
+ " has no default and is not nullable.");
}
ConstantValueExpression const_expr =
new ConstantValueExpression();
expr = const_expr;
if (column.getDefaulttype() != 0)
{
const_expr.setValue(column.getDefaultvalue());
}
else
{
const_expr.setValue("NULL");
}
}
// set the expression type to match the corresponding Column.
// in reality, the expression will cast its resulting NValue to
// the intermediate table's tuple; but, that tuple takes its
// type from these expression types (for now). The tempTuple is
// eventually tableTuple::copy()'d into the persistent table
// and must match the persistent table's column type and size.
// A little round-about, I know. Will get better.
expr.setValueSize(column.getSize());
expr.setValueType(VoltType.get((byte)column.getType()));
// add column to the materialize node.
PlanColumn colInfo = m_context.getPlanColumn(expr, column.getTypeName());
materializeNode.appendOutputColumn(colInfo);
}
// connect the insert and the materialize nodes together
insertNode.addAndLinkChild(materializeNode);
AbstractPlanNode rootNode = insertNode;
if (m_singlePartition == false) {
// all sites to a scan -> send
// root site has many recvs feeding into a union
rootNode = insertCountInDMLPlan(rootNode);
SendPlanNode sendNode = new SendPlanNode(m_context, getNextPlanNodeId());
// this will make the child planfragment be sent to all partitions
sendNode.isMultiPartition = true;
sendNode.addAndLinkChild(rootNode);
ReceivePlanNode recvNode = new ReceivePlanNode(m_context, getNextPlanNodeId());
recvNode.addAndLinkChild(sendNode);
rootNode = recvNode;
// receive node requires the schema of its output table
recvNode.updateOutputColumns(m_catalogDb);
// add a count and send on top of the union
rootNode = addSumAndSendToDMLNode(rootNode, targetTable.getIsreplicated());
} else if (INCLUDE_SEND_FOR_ALL) {
// XXX: PAVLO
// rootNode = addCountAndSendToDMLNode(rootNode);
SendPlanNode sendNode = new SendPlanNode(m_context, getNextPlanNodeId());
sendNode.setFake(true);
sendNode.addAndLinkChild(insertNode);
sendNode.setOutputColumns(insertNode.getOutputColumnGUIDs());
rootNode = sendNode;
}
return rootNode;
}