use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.
the class AbstractScanPlanNode method resolveColumnIndexes.
@Override
public void resolveColumnIndexes() {
// The following applies to both seq and index scan. Index scan has
// some additional expressions that need to be handled as well
// predicate expression
List<TupleValueExpression> predicate_tves = ExpressionUtil.getTupleValueExpressions(m_predicate);
for (TupleValueExpression tve : predicate_tves) {
tve.setColumnIndexUsingSchema(m_tableSchema);
}
// inline projection and insert
InsertPlanNode ins = (InsertPlanNode) getInlinePlanNode(PlanNodeType.INSERT);
ProjectionPlanNode proj = (ProjectionPlanNode) getInlinePlanNode(PlanNodeType.PROJECTION);
// Resolve the inline projection and insert if there are any.
if (proj != null) {
proj.resolveColumnIndexesUsingSchema(m_tableSchema);
}
if (ins != null) {
ins.resolveColumnIndexes();
}
// if there are any, in that order.
if (ins != null) {
m_outputSchema = ins.getOutputSchema().clone();
} else if (proj != null) {
m_outputSchema = proj.getOutputSchema().clone();
} else {
m_outputSchema = m_preAggOutputSchema;
// and sort them by table schema index order.
for (SchemaColumn col : m_outputSchema.getColumns()) {
AbstractExpression colExpr = col.getExpression();
// At this point, they'd better all be TVEs.
assert (colExpr instanceof TupleValueExpression);
TupleValueExpression tve = (TupleValueExpression) colExpr;
tve.setColumnIndexUsingSchema(m_tableSchema);
}
m_outputSchema.sortByTveIndex();
}
// The outputschema of an inline limit node is completely irrelevant to the EE except that
// serialization will complain if it contains expressions of unresolved columns.
// Logically, the limited scan output has the same schema as the pre-limit scan.
// It's at least as easy to just re-use the known-good output schema of the scan
// than it would be to carefully resolve the limit node's current output schema.
// And this simply works regardless of whether the limit was originally applied or inlined
// before or after the (possibly inline) projection.
// There's no need to be concerned about re-adjusting the irrelevant outputschema
// based on the different schema of the original raw scan and the projection.
LimitPlanNode limit = (LimitPlanNode) getInlinePlanNode(PlanNodeType.LIMIT);
if (limit != null) {
limit.m_outputSchema = m_outputSchema.clone();
// It's just another cheap knock-off
limit.m_hasSignificantOutputSchema = false;
}
// Resolve subquery expression indexes
resolveSubqueryColumnIndexes();
AggregatePlanNode aggNode = AggregatePlanNode.getInlineAggregationNode(this);
if (aggNode != null) {
aggNode.resolveColumnIndexesUsingSchema(m_outputSchema);
m_outputSchema = aggNode.getOutputSchema().copyAndReplaceWithTVE();
// Aggregate plan node change its output schema, and
// EE does not have special code to get output schema from inlined aggregate node.
m_hasSignificantOutputSchema = true;
}
}
use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.
the class AggregatePlanNode method isTableCountNonDistinctNullableColumn.
public boolean isTableCountNonDistinctNullableColumn() {
if (!isTableNonDistinctCount()) {
return false;
}
// Is the expression a column?
AbstractExpression aggArgument = m_aggregateExpressions.get(0);
if (!aggArgument.getExpressionType().equals(ExpressionType.VALUE_TUPLE)) {
return false;
}
// If the query is a join query then the child will be something like nested loop.
assert (m_children.size() == 1);
if (!(m_children.get(0) instanceof AbstractScanPlanNode)) {
return false;
}
AbstractScanPlanNode asp = (AbstractScanPlanNode) m_children.get(0);
if (!(asp.getTableScan() instanceof StmtTargetTableScan)) {
return false;
}
StmtTargetTableScan sttscan = (StmtTargetTableScan) asp.getTableScan();
Table tbl = sttscan.getTargetTable();
TupleValueExpression tve = (TupleValueExpression) aggArgument;
String columnName = tve.getColumnName();
Column col = tbl.getColumns().get(columnName);
// Is the column nullable?
if (col.getNullable()) {
return false;
}
return true;
}
use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.
the class AbstractScanPlanNode method initPreAggOutputSchema.
// Until the scan has an implicit projection rather than an explicitly
// inlined one, the output schema generation is going to be a bit odd.
// It will depend on three bits of state: whether any scan columns were
// specified for this table, whether or not there is an inlined
// projection and whether or not there is an inlined insert node.
// Note that only a seqscan node can have an inlined insert node,
// though support for index scan is expected.
//
// If there is an inlined insert or projection, then we'll just steal that
// output schema as our own, preferring insert to projection.
// If there is no inlined insert or projection, then, if there are no scan columns
// specified, use the entire table's schema as the output schema.
// Otherwise add an inline projection that projects the scan columns
// and then take that output schema as our own.
// These have the effect of repeatably generating the correct output
// schema if called again and again, but also allowing the planner
// to overwrite the inline projection and still have the right thing
// happen.
//
// Note that when an index scan is inlined into a join node (as with
// nested loop index joins), then there will be a project node inlined into
// the index scan node that determines which columns from the inner table
// are used as an output of the join, but that predicates evaluated against
// this table should use the complete schema of the table being scanned.
// See also the comments in NestLoopIndexPlanNode.resolveColumnIndexes.
// Related tickets: ENG-9389, ENG-9533.
private void initPreAggOutputSchema() {
InsertPlanNode ins = (InsertPlanNode) getInlinePlanNode(PlanNodeType.INSERT);
ProjectionPlanNode proj = (ProjectionPlanNode) getInlinePlanNode(PlanNodeType.PROJECTION);
if (ins != null) {
// If this is has an inline insert, then just make the
// output schema copied from the insert node.
m_outputSchema = ins.getOutputSchema().copyAndReplaceWithTVE();
m_hasSignificantOutputSchema = true;
} else if (proj != null) {
// Does this operation needs to change complex expressions
// into tuple value expressions with an column alias?
// Is this always true for clone? Or do we need a new method?
m_outputSchema = proj.getOutputSchema().copyAndReplaceWithTVE();
// It's just a cheap knock-off of the projection's
m_hasSignificantOutputSchema = false;
} else if (m_tableScanSchema.size() != 0) {
// Order the scan columns according to the table schema
// before we stick them in the projection output
int difftor = 0;
for (SchemaColumn col : m_tableScanSchema.getColumns()) {
col.setDifferentiator(difftor);
++difftor;
AbstractExpression colExpr = col.getExpression();
assert (colExpr instanceof TupleValueExpression);
TupleValueExpression tve = (TupleValueExpression) colExpr;
tve.setColumnIndexUsingSchema(m_tableSchema);
}
// and update their indexes against the table schema
m_tableScanSchema.sortByTveIndex();
// Create inline projection to map table outputs to scan outputs
ProjectionPlanNode projectionNode = new ProjectionPlanNode(m_tableScanSchema);
addInlinePlanNode(projectionNode);
// a bit redundant but logically consistent
m_outputSchema = projectionNode.getOutputSchema().copyAndReplaceWithTVE();
// It's just a cheap knock-off of the projection's
m_hasSignificantOutputSchema = false;
} else {
// We come here if m_tableScanSchema is empty.
//
// m_tableScanSchema might be empty for cases like
// select now from table;
// where there are no columns in the table that are accessed.
//
// Just fill m_outputSchema with the table's columns.
m_outputSchema = m_tableSchema.clone();
m_hasSignificantOutputSchema = true;
}
m_preAggOutputSchema = m_outputSchema;
}
use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.
the class NestLoopIndexPlanNode method resolveColumnIndexes.
@Override
public void resolveColumnIndexes() {
IndexScanPlanNode inlineScan = (IndexScanPlanNode) m_inlineNodes.get(PlanNodeType.INDEXSCAN);
assert (m_children.size() == 1 && inlineScan != null);
for (AbstractPlanNode child : m_children) {
child.resolveColumnIndexes();
}
LimitPlanNode limit = (LimitPlanNode) getInlinePlanNode(PlanNodeType.LIMIT);
if (limit != null) {
// output schema of limit node has not been used
limit.m_outputSchema = m_outputSchemaPreInlineAgg;
limit.m_hasSignificantOutputSchema = false;
}
// We need the schema from the target table from the inlined index
final NodeSchema completeInnerTableSchema = inlineScan.getTableSchema();
// We need the output schema from the child node
final NodeSchema outerSchema = m_children.get(0).getOutputSchema();
// pull every expression out of the inlined index scan
// and resolve all of the TVEs against our two input schema from above.
//
// Tickets ENG-9389, ENG-9533: we use the complete schema for the inner
// table (rather than the smaller schema from the inlined index scan's
// inlined project node) because the inlined scan has no temp table,
// so predicates will be accessing the index-scanned table directly.
resolvePredicate(inlineScan.getPredicate(), outerSchema, completeInnerTableSchema);
resolvePredicate(inlineScan.getEndExpression(), outerSchema, completeInnerTableSchema);
resolvePredicate(inlineScan.getInitialExpression(), outerSchema, completeInnerTableSchema);
resolvePredicate(inlineScan.getSkipNullPredicate(), outerSchema, completeInnerTableSchema);
resolvePredicate(inlineScan.getSearchKeyExpressions(), outerSchema, completeInnerTableSchema);
resolvePredicate(m_preJoinPredicate, outerSchema, completeInnerTableSchema);
resolvePredicate(m_joinPredicate, outerSchema, completeInnerTableSchema);
resolvePredicate(m_wherePredicate, outerSchema, completeInnerTableSchema);
// Resolve subquery expression indexes
resolveSubqueryColumnIndexes();
// Resolve TVE indexes for each schema column.
for (int i = 0; i < m_outputSchemaPreInlineAgg.size(); ++i) {
SchemaColumn col = m_outputSchemaPreInlineAgg.getColumns().get(i);
// These are all TVEs.
assert (col.getExpression() instanceof TupleValueExpression);
TupleValueExpression tve = (TupleValueExpression) col.getExpression();
int index;
int tableIdx;
if (i < outerSchema.size()) {
// 0 for outer table
tableIdx = 0;
index = outerSchema.getIndexOfTve(tve);
if (index >= 0) {
tve.setColumnIndex(index);
}
} else {
// 1 for inner table
tableIdx = 1;
index = tve.setColumnIndexUsingSchema(completeInnerTableSchema);
}
if (index == -1) {
throw new RuntimeException("Unable to find index for column: " + col.toString());
}
tve.setTableIndex(tableIdx);
}
// We want the output columns to be ordered like [outer table columns][inner table columns],
// and further ordered by TVE index within the left- and righthand sides.
// generateOutputSchema already places outer columns on the left and inner on the right,
// so we just need to order the left- and righthand sides by TVE index separately.
m_outputSchemaPreInlineAgg.sortByTveIndex(0, outerSchema.size());
m_outputSchemaPreInlineAgg.sortByTveIndex(outerSchema.size(), m_outputSchemaPreInlineAgg.size());
m_hasSignificantOutputSchema = true;
resolveRealOutputSchema();
}
use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.
the class NodeSchema method replaceTableClone.
public NodeSchema replaceTableClone(String tableAlias) {
NodeSchema copy = new NodeSchema();
for (int colIndex = 0; colIndex < m_columns.size(); ++colIndex) {
SchemaColumn column = m_columns.get(colIndex);
String colAlias = column.getColumnAlias();
int differentiator = column.getDifferentiator();
TupleValueExpression tve = new TupleValueExpression(tableAlias, tableAlias, colAlias, colAlias, colIndex, differentiator);
tve.setTypeSizeAndInBytes(column);
copy.addColumn(tableAlias, tableAlias, colAlias, colAlias, tve, differentiator);
}
return copy;
}
Aggregations