use of org.voltdb.plannodes.SchemaColumn in project voltdb by VoltDB.
the class TestUnion method checkOrderByNode.
private void checkOrderByNode(AbstractPlanNode pn, String[] columns, int[] idxs) {
assertTrue(pn != null);
assertTrue(pn instanceof OrderByPlanNode);
OrderByPlanNode opn = (OrderByPlanNode) pn;
assertEquals(columns.length, opn.getOutputSchema().size());
for (int i = 0; i < columns.length; ++i) {
SchemaColumn col = opn.getOutputSchema().getColumns().get(i);
assertEquals(columns[i], col.getColumnAlias());
AbstractExpression colExpr = col.getExpression();
assertEquals(ExpressionType.VALUE_TUPLE, colExpr.getExpressionType());
assertEquals(idxs[i], ((TupleValueExpression) colExpr).getColumnIndex());
}
}
use of org.voltdb.plannodes.SchemaColumn in project voltdb by VoltDB.
the class MaterializedViewFixInfo method processMVBasedQueryFix.
/**
* Check whether the results from a materialized view need to be
* re-aggregated on the coordinator by the view's GROUP BY columns
* prior to any of the processing specified by the query.
* This is normally the case when a mat view's source table is partitioned
* and the view's GROUP BY does not include the partition key.
* There is a special edge case where the query already contains the exact
* reaggregations that the added-cost fix would introduce, so the fix can
* be skipped as an optimization.
* Set the m_needed flag to true, only if the reaggregation fix is needed.
* @return The value of m_needed
*/
public boolean processMVBasedQueryFix(StmtTableScan mvTableScan, Set<SchemaColumn> scanColumns, JoinNode joinTree, List<ParsedColInfo> displayColumns, List<ParsedColInfo> groupByColumns) {
//@TODO
if (!(mvTableScan instanceof StmtTargetTableScan)) {
return false;
}
Table table = ((StmtTargetTableScan) mvTableScan).getTargetTable();
assert (table != null);
String mvTableName = table.getTypeName();
Table srcTable = table.getMaterializer();
if (srcTable == null) {
return false;
}
if (table.getIsreplicated()) {
return false;
}
// Justify whether partition column is in group by column list or not
if (table.getPartitioncolumn() != null) {
return false;
}
m_mvTableScan = mvTableScan;
Set<String> mvDDLGroupbyColumnNames = new HashSet<>();
List<Column> mvColumnArray = CatalogUtil.getSortedCatalogItems(table.getColumns(), "index");
String mvTableAlias = getMVTableAlias();
// Get the number of group-by columns.
int numOfGroupByColumns;
MaterializedViewInfo mvInfo = srcTable.getViews().get(mvTableName);
if (mvInfo != null) {
// single table view
String complexGroupbyJson = mvInfo.getGroupbyexpressionsjson();
if (complexGroupbyJson.length() > 0) {
List<AbstractExpression> mvComplexGroupbyCols = null;
try {
mvComplexGroupbyCols = AbstractExpression.fromJSONArrayString(complexGroupbyJson, null);
} catch (JSONException e) {
e.printStackTrace();
}
numOfGroupByColumns = mvComplexGroupbyCols.size();
} else {
numOfGroupByColumns = mvInfo.getGroupbycols().size();
}
} else {
// joined table view
MaterializedViewHandlerInfo mvHandlerInfo = table.getMvhandlerinfo().get("mvHandlerInfo");
numOfGroupByColumns = mvHandlerInfo.getGroupbycolumncount();
}
if (scanColumns.isEmpty() && numOfGroupByColumns == 0) {
// This is an edge case that can happen if the view
// has no group by keys, and we are just
// doing a count(*) on the output of the view.
//
// Having no GB keys or scan columns would cause us to
// produce plan nodes that have a 0-column output schema.
// We can't handle this in several places, so add the
// count(*) column from the view to the scan columns.
// this is the "count(*)" column.
Column mvCol = mvColumnArray.get(0);
TupleValueExpression tve = new TupleValueExpression(mvTableName, mvTableAlias, mvCol, 0);
tve.setOrigStmtId(mvTableScan.getStatementId());
String colName = mvCol.getName();
SchemaColumn scol = new SchemaColumn(mvTableName, mvTableAlias, colName, colName, tve);
scanColumns.add(scol);
}
// Start to do real materialized view processing to fix the duplicates problem.
// (1) construct new projection columns for scan plan node.
Set<SchemaColumn> mvDDLGroupbyColumns = new HashSet<>();
NodeSchema inlineProjSchema = new NodeSchema();
for (SchemaColumn scol : scanColumns) {
inlineProjSchema.addColumn(scol);
}
for (int i = 0; i < numOfGroupByColumns; i++) {
Column mvCol = mvColumnArray.get(i);
String colName = mvCol.getName();
TupleValueExpression tve = new TupleValueExpression(mvTableName, mvTableAlias, mvCol, i);
tve.setOrigStmtId(mvTableScan.getStatementId());
mvDDLGroupbyColumnNames.add(colName);
SchemaColumn scol = new SchemaColumn(mvTableName, mvTableAlias, colName, colName, tve);
mvDDLGroupbyColumns.add(scol);
if (!scanColumns.contains(scol)) {
scanColumns.add(scol);
// construct new projection columns for scan plan node.
inlineProjSchema.addColumn(scol);
}
}
// Record the re-aggregation type for each scan columns.
Map<String, ExpressionType> mvColumnReAggType = new HashMap<>();
for (int i = numOfGroupByColumns; i < mvColumnArray.size(); i++) {
Column mvCol = mvColumnArray.get(i);
ExpressionType reAggType = ExpressionType.get(mvCol.getAggregatetype());
if (reAggType == ExpressionType.AGGREGATE_COUNT_STAR || reAggType == ExpressionType.AGGREGATE_COUNT) {
reAggType = ExpressionType.AGGREGATE_SUM;
}
mvColumnReAggType.put(mvCol.getName(), reAggType);
}
assert (inlineProjSchema.size() > 0);
m_scanInlinedProjectionNode = new ProjectionPlanNode(inlineProjSchema);
// (2) Construct the reAggregation Node.
// Construct the reAggregation plan node's aggSchema
m_reAggNode = new HashAggregatePlanNode();
int outputColumnIndex = 0;
// inlineProjSchema contains the group by columns, while aggSchema may do not.
NodeSchema aggSchema = new NodeSchema();
// Construct reAggregation node's aggregation and group by list.
for (SchemaColumn scol : inlineProjSchema.getColumns()) {
if (mvDDLGroupbyColumns.contains(scol)) {
// Add group by expression.
m_reAggNode.addGroupByExpression(scol.getExpression());
} else {
ExpressionType reAggType = mvColumnReAggType.get(scol.getColumnName());
assert (reAggType != null);
AbstractExpression agg_input_expr = scol.getExpression();
assert (agg_input_expr instanceof TupleValueExpression);
// Add aggregation information.
m_reAggNode.addAggregate(reAggType, false, outputColumnIndex, agg_input_expr);
}
aggSchema.addColumn(scol);
outputColumnIndex++;
}
assert (aggSchema.size() > 0);
m_reAggNode.setOutputSchema(aggSchema);
// Collect all TVEs that need to be do re-aggregation in coordinator.
List<TupleValueExpression> needReAggTVEs = new ArrayList<>();
List<AbstractExpression> aggPostExprs = new ArrayList<>();
for (int i = numOfGroupByColumns; i < mvColumnArray.size(); i++) {
Column mvCol = mvColumnArray.get(i);
TupleValueExpression tve = new TupleValueExpression(mvTableName, mvTableAlias, mvCol, -1);
tve.setOrigStmtId(mvTableScan.getStatementId());
needReAggTVEs.add(tve);
}
collectReAggNodePostExpressions(joinTree, needReAggTVEs, aggPostExprs);
AbstractExpression aggPostExpr = ExpressionUtil.combinePredicates(aggPostExprs);
// Add post filters for the reAggregation node.
m_reAggNode.setPostPredicate(aggPostExpr);
// ENG-5386
if (m_edgeCaseQueryNoFixNeeded && edgeCaseQueryNoFixNeeded(mvDDLGroupbyColumnNames, mvColumnReAggType, displayColumns, groupByColumns)) {
return false;
}
m_needed = true;
return true;
}
use of org.voltdb.plannodes.SchemaColumn in project voltdb by VoltDB.
the class ParsedSelectStmt method prepareMVBasedQueryFix.
/**
* Prepare for the mv based distributed query fix only if it might be required.
*/
private void prepareMVBasedQueryFix() {
// aggregation push down does not need reAggregation work.
if (m_hasComplexGroupby) {
m_mvFixInfo.setEdgeCaseQueryNoFixNeeded(false);
}
// that need to be fixed should not exceed one.
for (StmtTableScan mvTableScan : allScans()) {
Set<SchemaColumn> mvNewScanColumns = new HashSet<>();
Collection<SchemaColumn> columns = mvTableScan.getScanColumns();
// TB has no scan columns
if (columns != null) {
mvNewScanColumns.addAll(columns);
}
// also need to be checked.
if (m_mvFixInfo.processMVBasedQueryFix(mvTableScan, mvNewScanColumns, m_joinTree, m_aggResultColumns, groupByColumns())) {
break;
}
}
}
use of org.voltdb.plannodes.SchemaColumn in project voltdb by VoltDB.
the class ParsedSelectStmt method isPartitionColumnInWindowedAggregatePartitionByList.
/**
* Return true iff all the windowed partition expressions
* have a table partition column in their partition by list,
* and if there is one such windowed partition expression.
* If there are no windowed expressions, we return false.
* Note that there can only be one windowed
* expression currently, so this is more general than it needs to be.
*
* @return
*/
public boolean isPartitionColumnInWindowedAggregatePartitionByList() {
if (getWindowFunctionExpressions().size() == 0) {
return false;
}
// If we ever do, this should fail gracelessly.
assert (getWindowFunctionExpressions().size() == 1);
WindowFunctionExpression we = getWindowFunctionExpressions().get(0);
List<AbstractExpression> partitionByExprs = we.getPartitionByExpressions();
boolean foundPartExpr = false;
for (AbstractExpression ae : partitionByExprs) {
if (!(ae instanceof TupleValueExpression)) {
continue;
}
TupleValueExpression tve = (TupleValueExpression) ae;
String tableAlias = tve.getTableAlias();
String columnName = tve.getColumnName();
StmtTableScan scanTable = getStmtTableScanByAlias(tableAlias);
if (scanTable == null || scanTable.getPartitioningColumns() == null) {
continue;
}
boolean foundPartCol = false;
for (SchemaColumn pcol : scanTable.getPartitioningColumns()) {
if (pcol != null && pcol.getColumnName().equals(columnName)) {
foundPartCol = true;
break;
}
}
// in this windowed expression.
if (foundPartCol) {
foundPartExpr = true;
break;
}
}
return foundPartExpr;
}
use of org.voltdb.plannodes.SchemaColumn in project voltdb by VoltDB.
the class StmtSubqueryScan method addPartitioningColumns.
private void addPartitioningColumns(List<SchemaColumn> scols) {
// in order to be referenced on parent level.
for (SchemaColumn partitionCol : scols) {
SchemaColumn matchedCol = null;
// Find whether the partition column is in output column list
for (SchemaColumn outputCol : m_outputColumnList) {
AbstractExpression outputExpr = outputCol.getExpression();
if (!(outputExpr instanceof TupleValueExpression)) {
continue;
}
TupleValueExpression tve = (TupleValueExpression) outputExpr;
if (tve.getTableName().equals(partitionCol.getTableName()) && tve.getColumnName().equals(partitionCol.getColumnName())) {
matchedCol = outputCol;
break;
}
}
String colNameForParentQuery;
if (matchedCol != null) {
colNameForParentQuery = matchedCol.getColumnAlias();
} else // including partition column in its display column list
if (!m_subqueriesPartitioning.requiresTwoFragments()) {
colNameForParentQuery = partitionCol.getColumnName();
} else {
continue;
}
partitionCol.reset(m_tableAlias, m_tableAlias, colNameForParentQuery, colNameForParentQuery);
m_partitioningColumns.add(partitionCol);
}
}
Aggregations