use of org.voltdb.expressions.ConstantValueExpression in project voltdb by VoltDB.
the class AbstractParsedStmt method addHonoraryOrderByExpressions.
/**
* Given a set of order-by expressions and a select list, which is a list of
* columns, each with an expression and an alias, expand the order-by list
* with new expressions which could be on the order-by list without changing
* the sort order and which are otherwise helpful.
*/
protected void addHonoraryOrderByExpressions(HashSet<AbstractExpression> orderByExprs, List<ParsedColInfo> candidateColumns) {
// of joins is the content of ticket ENG-8677.
if (m_tableAliasMap.size() != 1) {
return;
}
HashMap<AbstractExpression, Set<AbstractExpression>> valueEquivalence = analyzeValueEquivalence();
for (ParsedColInfo colInfo : candidateColumns) {
AbstractExpression colExpr = colInfo.expression;
if (colExpr instanceof TupleValueExpression) {
Set<AbstractExpression> tveEquivs = valueEquivalence.get(colExpr);
if (tveEquivs != null) {
for (AbstractExpression expr : tveEquivs) {
if (expr instanceof ParameterValueExpression || expr instanceof ConstantValueExpression) {
orderByExprs.add(colExpr);
}
}
}
}
}
// We know there's exactly one.
StmtTableScan scan = m_tableAliasMap.values().iterator().next();
// Get the table. There's only one.
Table table = getTableFromDB(scan.getTableName());
// there's no use to continue.
if (table == null) {
return;
}
// Now, look to see if there is a constraint which can help us.
// If there is a unique constraint on a set of columns, and all
// the constrained columns are in the order by list, then all
// the columns in the table can be added to the order by list.
//
// The indices we care about have columns, but the order by list has expressions.
// Extract the columns from the order by list.
Set<Column> orderByColumns = new HashSet<>();
for (AbstractExpression expr : orderByExprs) {
if (expr instanceof TupleValueExpression) {
TupleValueExpression tve = (TupleValueExpression) expr;
Column col = table.getColumns().get(tve.getColumnName());
orderByColumns.add(col);
}
}
CatalogMap<Constraint> constraints = table.getConstraints();
// If we have no constraints, there's nothing more to do here.
if (constraints == null) {
return;
}
Set<Index> indices = new HashSet<>();
for (Constraint constraint : constraints) {
Index index = constraint.getIndex();
// Only use column indices for now.
if (index != null && index.getUnique() && index.getExpressionsjson().isEmpty()) {
indices.add(index);
}
}
for (ParsedColInfo colInfo : candidateColumns) {
AbstractExpression expr = colInfo.expression;
if (expr instanceof TupleValueExpression) {
TupleValueExpression tve = (TupleValueExpression) expr;
// So, we remember this and early-out.
for (Index index : indices) {
CatalogMap<ColumnRef> columns = index.getColumns();
// If all the columns in this index are in the current
// honorary order by list, then we can add all the
// columns in this table to the honorary order by list.
boolean addAllColumns = true;
for (ColumnRef cr : columns) {
Column col = cr.getColumn();
if (orderByColumns.contains(col) == false) {
addAllColumns = false;
break;
}
}
if (addAllColumns) {
for (Column addCol : table.getColumns()) {
// We have to convert this to a TVE to add
// it to the orderByExprs. We will use -1
// for the column index. We don't have a column
// alias.
TupleValueExpression ntve = new TupleValueExpression(tve.getTableName(), tve.getTableAlias(), addCol.getName(), null, -1);
orderByExprs.add(ntve);
}
// Don't forget to remember to forget the other indices. (E. Presley, 1955)
break;
}
}
}
}
}
use of org.voltdb.expressions.ConstantValueExpression in project voltdb by VoltDB.
the class AbstractParsedStmt method producesOneRowOutput.
// Function evaluates whether the statement results in at most
// one output row. This is implemented for single table by checking
// value equivalence of predicates in where clause and checking
// if all defined unique indexes are in value equivalence set.
// Returns true if the statement results is at most one output
// row else false
protected boolean producesOneRowOutput() {
if (m_tableAliasMap.size() != 1) {
return false;
}
// Get the table. There's only one.
StmtTableScan scan = m_tableAliasMap.values().iterator().next();
Table table = getTableFromDB(scan.getTableName());
// May be sub-query? If can't find the table there's no use to continue.
if (table == null) {
return false;
}
// Get all the indexes defined on the table
CatalogMap<Index> indexes = table.getIndexes();
if (indexes == null || indexes.size() == 0) {
// no indexes defined on the table
return false;
}
// Collect value equivalence expression for the SQL statement
HashMap<AbstractExpression, Set<AbstractExpression>> valueEquivalence = analyzeValueEquivalence();
// If no value equivalence filter defined in SQL statement, there's no use to continue
if (valueEquivalence.isEmpty()) {
return false;
}
// Collect all tve expressions from value equivalence set which have equivalence
// defined to parameterized or constant value expression.
// Eg: T.A = ? or T.A = 1
Set<AbstractExpression> parameterizedConstantKeys = new HashSet<>();
// get all the keys
Set<AbstractExpression> valueEquivalenceKeys = valueEquivalence.keySet();
for (AbstractExpression key : valueEquivalenceKeys) {
if (key instanceof TupleValueExpression) {
Set<AbstractExpression> values = valueEquivalence.get(key);
for (AbstractExpression value : values) {
if ((value instanceof ParameterValueExpression) || (value instanceof ConstantValueExpression)) {
TupleValueExpression tve = (TupleValueExpression) key;
parameterizedConstantKeys.add(tve);
}
}
}
}
// index defined on table appears in tve equivalence expression gathered above.
for (Index index : indexes) {
// Perform lookup only on pure column indices which are unique
if (!index.getUnique() || !index.getExpressionsjson().isEmpty()) {
continue;
}
Set<AbstractExpression> indexExpressions = new HashSet<>();
CatalogMap<ColumnRef> indexColRefs = index.getColumns();
for (ColumnRef indexColRef : indexColRefs) {
Column col = indexColRef.getColumn();
TupleValueExpression tve = new TupleValueExpression(scan.getTableName(), scan.getTableAlias(), col.getName(), col.getName(), col.getIndex());
indexExpressions.add(tve);
}
if (parameterizedConstantKeys.containsAll(indexExpressions)) {
return true;
}
}
return false;
}
use of org.voltdb.expressions.ConstantValueExpression 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.ConstantValueExpression in project voltdb by VoltDB.
the class ParsedSelectStmt method parseOrderColumn.
private void parseOrderColumn(VoltXMLElement orderByNode, final boolean isDistributed) {
// Aggregation list needs to be cleared before parsing the order by expression
m_aggregationList.clear();
ParsedColInfo.ExpressionAdjuster adjuster = new ParsedColInfo.ExpressionAdjuster() {
@Override
public AbstractExpression adjust(AbstractExpression expr) {
if (isDistributed) {
expr = expr.replaceAVG();
updateAvgExpressions();
}
ExpressionUtil.finalizeValueTypes(expr);
return expr;
}
};
ParsedColInfo order_col = ParsedColInfo.fromOrderByXml(this, orderByNode, adjuster);
AbstractExpression order_exp = order_col.expression;
assert (order_exp != null);
// guards against subquery inside of order by clause
if (order_exp.hasSubquerySubexpression()) {
throw new PlanningErrorException("ORDER BY clauses with subquery expressions are not allowed.");
}
// (for determinism).
for (ParsedColInfo col : m_displayColumns) {
if (col.alias.equals(order_col.alias) || col.expression.equals(order_exp)) {
col.orderBy = true;
col.ascending = order_col.ascending;
order_col.alias = col.alias;
order_col.columnName = col.columnName;
order_col.tableName = col.tableName;
break;
}
}
assert (!(order_exp instanceof ConstantValueExpression));
assert (!(order_exp instanceof ParameterValueExpression));
insertAggExpressionsToAggResultColumns(m_aggregationList, order_col);
if (m_aggregationList.size() >= 1) {
m_hasAggregateExpression = true;
}
// Add TVEs in ORDER BY statement if we have,
// stop recursive finding when we have it in AggResultColumns
List<TupleValueExpression> tveList = new ArrayList<>();
findAllTVEs(order_col.expression, tveList);
insertTVEsToAggResultColumns(tveList);
m_orderColumns.add(order_col);
}
use of org.voltdb.expressions.ConstantValueExpression in project voltdb by VoltDB.
the class PlanAssembler method canPushDownDistinctAggregation.
private boolean canPushDownDistinctAggregation(AggregateExpression aggExpr) {
assert (m_parsedSelect != null);
assert (aggExpr != null);
assert (aggExpr.isDistinct());
if (aggExpr.getExpressionType() == ExpressionType.AGGREGATE_COUNT_STAR) {
return true;
}
AbstractExpression aggArg = aggExpr.getLeft();
// constant
if (aggArg instanceof ConstantValueExpression || aggArg instanceof ParameterValueExpression) {
return true;
}
if (!(aggArg instanceof TupleValueExpression)) {
return false;
}
TupleValueExpression tve = (TupleValueExpression) aggArg;
String tableAlias = tve.getTableAlias();
StmtTableScan scanTable = m_parsedSelect.getStmtTableScanByAlias(tableAlias);
// table alias may be from AbstractParsedStmt.TEMP_TABLE_NAME.
if (scanTable == null || scanTable.getPartitioningColumns() == null) {
return false;
}
for (SchemaColumn pcol : scanTable.getPartitioningColumns()) {
if (pcol != null && pcol.getColumnName().equals(tve.getColumnName())) {
return true;
}
}
return false;
}
Aggregations