use of org.voltdb.expressions.TupleAddressExpression in project voltdb by VoltDB.
the class TestScanPlanNode method testOutputSchemaOverriddenProjection.
// test that if someone provides their own inline projection
// that the output schema of the scan node consists of the output
// schema of the projection. Updates will do this so that the
// inlined projection fills the values of the output tuples correctly
// before it attempts to update them
public void testOutputSchemaOverriddenProjection() {
AbstractScanPlanNode dut = new SeqScanPlanNode(TABLE1, TABLE1);
// Create an output schema like we might see for an inlined projection
// generated for update. We'll have 4 output columns, the first will
// be the tuple address, the second one a parameter expression, next
// will be a constant, and the other will be a more complex expression
// that uses some TVEs.
NodeSchema proj_schema = new NodeSchema();
String[] cols = new String[4];
TupleAddressExpression col1_exp = new TupleAddressExpression();
proj_schema.addColumn("", "", "tuple_address", "tuple_address", col1_exp);
cols[0] = "tuple_address";
// update column 1 with a parameter value
ParameterValueExpression col2_exp = new ParameterValueExpression();
col2_exp.setParameterIndex(0);
col2_exp.setValueType(COLTYPES[1]);
col2_exp.setValueSize(COLTYPES[1].getLengthInBytesForFixedTypes());
// XXX I'm not sure what to do with the name for the updated column yet.
// I think it should be an alias and not the original table name/col name
proj_schema.addColumn(TABLE1, TABLE1, COLS[1], COLS[1], col2_exp);
cols[1] = COLS[1];
// Update column 3 with a constant value
ConstantValueExpression col3_exp = new ConstantValueExpression();
col3_exp.setValueType(COLTYPES[3]);
col3_exp.setValueSize(COLTYPES[3].getLengthInBytesForFixedTypes());
col3_exp.setValue("3.14159");
proj_schema.addColumn(TABLE1, TABLE1, COLS[3], COLS[3], col3_exp);
cols[2] = COLS[3];
// update column 4 with a sum of columns 0 and 2
OperatorExpression col4_exp = new OperatorExpression();
col4_exp.setValueType(COLTYPES[4]);
col4_exp.setValueSize(COLTYPES[4].getLengthInBytesForFixedTypes());
col4_exp.setExpressionType(ExpressionType.OPERATOR_PLUS);
TupleValueExpression left = new TupleValueExpression(TABLE1, TABLE1, COLS[0], COLS[0], 0);
left.setValueType(COLTYPES[0]);
left.setValueSize(COLTYPES[0].getLengthInBytesForFixedTypes());
TupleValueExpression right = new TupleValueExpression(TABLE1, TABLE1, COLS[2], COLS[2], 0);
right.setValueType(COLTYPES[2]);
right.setValueSize(COLTYPES[2].getLengthInBytesForFixedTypes());
col4_exp.setLeft(left);
col4_exp.setRight(right);
proj_schema.addColumn(TABLE1, TABLE1, COLS[4], "C1", col4_exp);
cols[3] = COLS[4];
ProjectionPlanNode proj_node = new ProjectionPlanNode(proj_schema);
dut.addInlinePlanNode(proj_node);
System.out.println("ProjSchema: " + proj_schema.toString());
dut.generateOutputSchema(m_voltdb.getDatabase());
NodeSchema dut_schema = dut.getOutputSchema();
System.out.println(dut_schema.toString());
for (int i = 0; i < cols.length; i++) {
SchemaColumn col = null;
if (i == 0) {
col = dut_schema.find("", "", cols[i], cols[i]);
} else {
col = dut_schema.find(TABLE1, TABLE1, cols[i], cols[i]);
}
assertNotNull(col);
assertEquals(col.getExpression().getExpressionType(), ExpressionType.VALUE_TUPLE);
}
}
use of org.voltdb.expressions.TupleAddressExpression in project voltdb by VoltDB.
the class PlanAssembler method getNextDeletePlan.
private CompiledPlan getNextDeletePlan() {
assert (m_subAssembler != null);
// figure out which table we're deleting from
assert (m_parsedDelete.m_tableList.size() == 1);
Table targetTable = m_parsedDelete.m_tableList.get(0);
AbstractPlanNode subSelectRoot = m_subAssembler.nextPlan();
if (subSelectRoot == null) {
return null;
}
// ENG-4909 Bug: currently disable NESTLOOPINDEX plan for IN
if (disableNestedLoopIndexJoinForInComparison(subSelectRoot, m_parsedDelete)) {
// simply jumps ahead to the next plan (if any).
return getNextDeletePlan();
}
boolean isSinglePartitionPlan = m_partitioning.wasSpecifiedAsSingle() || m_partitioning.isInferredSingle();
// generate the delete node with the right target table
DeletePlanNode deleteNode = new DeletePlanNode();
deleteNode.setTargetTableName(targetTable.getTypeName());
assert (subSelectRoot instanceof AbstractScanPlanNode);
// nodes and use a truncate delete node.
if (deleteIsTruncate(m_parsedDelete, subSelectRoot)) {
deleteNode.setTruncate(true);
} else {
// User may have specified an ORDER BY ... LIMIT clause
if (m_parsedDelete.orderByColumns().size() > 0 && !isSinglePartitionPlan && !targetTable.getIsreplicated()) {
throw new PlanningErrorException("DELETE statements affecting partitioned tables must " + "be able to execute on one partition " + "when ORDER BY and LIMIT or OFFSET clauses " + "are present.");
}
boolean needsOrderByNode = isOrderByNodeRequired(m_parsedDelete, subSelectRoot);
AbstractExpression addressExpr = new TupleAddressExpression();
NodeSchema proj_schema = new NodeSchema();
// This planner-created column is magic.
proj_schema.addColumn(AbstractParsedStmt.TEMP_TABLE_NAME, AbstractParsedStmt.TEMP_TABLE_NAME, "tuple_address", "tuple_address", addressExpr);
if (needsOrderByNode) {
// Projection will need to pass the sort keys to the order by node
for (ParsedColInfo col : m_parsedDelete.orderByColumns()) {
proj_schema.addColumn(col.asSchemaColumn());
}
}
ProjectionPlanNode projectionNode = new ProjectionPlanNode(proj_schema);
subSelectRoot.addInlinePlanNode(projectionNode);
AbstractPlanNode root = subSelectRoot;
if (needsOrderByNode) {
OrderByPlanNode ob = buildOrderByPlanNode(m_parsedDelete.orderByColumns());
ob.addAndLinkChild(root);
root = ob;
}
if (m_parsedDelete.hasLimitOrOffset()) {
assert (m_parsedDelete.orderByColumns().size() > 0);
root.addInlinePlanNode(m_parsedDelete.limitPlanNode());
}
deleteNode.addAndLinkChild(root);
}
CompiledPlan plan = new CompiledPlan();
plan.setReadOnly(false);
// check non-determinism status
// treat this as deterministic for reporting purposes:
// delete statements produce just one row that is the
// number of rows affected
boolean orderIsDeterministic = true;
boolean hasLimitOrOffset = m_parsedDelete.hasLimitOrOffset();
// The delete statement cannot be inherently content non-deterministic.
// So, the last parameter is always null.
plan.statementGuaranteesDeterminism(hasLimitOrOffset, orderIsDeterministic, null);
if (isSinglePartitionPlan) {
plan.rootPlanGraph = deleteNode;
return plan;
}
// Add a compensating sum of modified tuple counts or a limit 1
// AND a send on top of the union-like receive node.
boolean isReplicated = targetTable.getIsreplicated();
plan.rootPlanGraph = addCoordinatorToDMLNode(deleteNode, isReplicated);
return plan;
}
use of org.voltdb.expressions.TupleAddressExpression in project voltdb by VoltDB.
the class PlanAssembler method getNextUpdatePlan.
private CompiledPlan getNextUpdatePlan() {
assert (m_subAssembler != null);
AbstractPlanNode subSelectRoot = m_subAssembler.nextPlan();
if (subSelectRoot == null) {
return null;
}
if (disableNestedLoopIndexJoinForInComparison(subSelectRoot, m_parsedUpdate)) {
// simply jumps ahead to the next plan (if any).
return getNextUpdatePlan();
}
UpdatePlanNode updateNode = new UpdatePlanNode();
// It was not in Mike A's original branch.
assert (m_parsedUpdate.m_tableList.size() == 1);
Table targetTable = m_parsedUpdate.m_tableList.get(0);
updateNode.setTargetTableName(targetTable.getTypeName());
// set this to false until proven otherwise
updateNode.setUpdateIndexes(false);
TupleAddressExpression tae = new TupleAddressExpression();
NodeSchema proj_schema = new NodeSchema();
// This planner-generated column is magic.
proj_schema.addColumn(AbstractParsedStmt.TEMP_TABLE_NAME, AbstractParsedStmt.TEMP_TABLE_NAME, "tuple_address", "tuple_address", tae);
// get the set of columns affected by indexes
Set<String> affectedColumns = getIndexedColumnSetForTable(targetTable);
// to avoid any false schema/column matches with the actual table.
for (Entry<Column, AbstractExpression> colEntry : m_parsedUpdate.columns.entrySet()) {
Column col = colEntry.getKey();
String colName = col.getTypeName();
AbstractExpression expr = colEntry.getValue();
expr.setInBytes(colEntry.getKey().getInbytes());
proj_schema.addColumn(AbstractParsedStmt.TEMP_TABLE_NAME, AbstractParsedStmt.TEMP_TABLE_NAME, colName, colName, expr);
// check if this column is an indexed column
if (affectedColumns.contains(colName)) {
updateNode.setUpdateIndexes(true);
}
}
ProjectionPlanNode projectionNode = new ProjectionPlanNode(proj_schema);
// in order to simply cull the columns from the persistent table.
assert (subSelectRoot instanceof AbstractScanPlanNode);
subSelectRoot.addInlinePlanNode(projectionNode);
// connect the nodes to build the graph
updateNode.addAndLinkChild(subSelectRoot);
CompiledPlan retval = new CompiledPlan();
retval.setReadOnly(false);
if (targetTable.getIsreplicated()) {
retval.replicatedTableDML = true;
}
//FIXME: This assumption was only safe when we didn't support updates
// w/ possibly non-deterministic subqueries.
// Is there some way to integrate a "subquery determinism" check here?
// because we didn't support updates with limits, either.
// Since the update cannot be inherently non-deterministic, there is
// no message, and the last parameter is null.
retval.statementGuaranteesDeterminism(false, true, null);
if (m_partitioning.wasSpecifiedAsSingle() || m_partitioning.isInferredSingle()) {
retval.rootPlanGraph = updateNode;
return retval;
}
// Send the local result counts to the coordinator.
// Add a compensating sum of modified tuple counts or a limit 1
// AND a send on top of the union-like receive node.
boolean isReplicated = targetTable.getIsreplicated();
retval.rootPlanGraph = addCoordinatorToDMLNode(updateNode, isReplicated);
return retval;
}
Aggregations