Search in sources :

Example 16 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan 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;
                }
            }
        }
    }
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) HashSet(java.util.HashSet) Set(java.util.Set) Table(org.voltdb.catalog.Table) Constraint(org.voltdb.catalog.Constraint) Index(org.voltdb.catalog.Index) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan) AbstractExpression(org.voltdb.expressions.AbstractExpression) Column(org.voltdb.catalog.Column) SchemaColumn(org.voltdb.plannodes.SchemaColumn) ConstantValueExpression(org.voltdb.expressions.ConstantValueExpression) ColumnRef(org.voltdb.catalog.ColumnRef) ParameterValueExpression(org.voltdb.expressions.ParameterValueExpression) HashSet(java.util.HashSet)

Example 17 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.

the class AbstractParsedStmt method addSimplifiedSubqueryToStmtCache.

/**
     * Replace an existing subquery scan with its underlying table scan. The subquery
     * has already passed all the checks from the canSimplifySubquery method.
     * Subquery ORDER BY clause is ignored if such exists.
     *
     * @param subqueryScan subquery scan to simplify
     * @param tableAlias
     * @return StmtTargetTableScan
     */
private StmtTargetTableScan addSimplifiedSubqueryToStmtCache(StmtSubqueryScan subqueryScan, StmtTargetTableScan tableScan) {
    String tableAlias = subqueryScan.getTableAlias();
    assert (tableAlias != null);
    // It is guaranteed by the canSimplifySubquery that there is
    // one and only one TABLE in the subquery's FROM clause.
    Table promotedTable = tableScan.getTargetTable();
    StmtTargetTableScan promotedScan = new StmtTargetTableScan(promotedTable, tableAlias, m_stmtId);
    // Keep the original subquery scan to be able to tie the parent
    // statement column/table names and aliases to the table's.
    promotedScan.setOriginalSubqueryScan(subqueryScan);
    // Replace the subquery scan with the table scan
    StmtTableScan prior = m_tableAliasMap.put(tableAlias, promotedScan);
    assert (prior == subqueryScan);
    m_tableList.add(promotedTable);
    return promotedScan;
}
Also used : Table(org.voltdb.catalog.Table) StmtTargetTableScan(org.voltdb.planner.parseinfo.StmtTargetTableScan) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan)

Example 18 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan 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;
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) Table(org.voltdb.catalog.Table) HashSet(java.util.HashSet) Set(java.util.Set) Index(org.voltdb.catalog.Index) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan) AbstractExpression(org.voltdb.expressions.AbstractExpression) Column(org.voltdb.catalog.Column) SchemaColumn(org.voltdb.plannodes.SchemaColumn) ConstantValueExpression(org.voltdb.expressions.ConstantValueExpression) ColumnRef(org.voltdb.catalog.ColumnRef) ParameterValueExpression(org.voltdb.expressions.ParameterValueExpression) HashSet(java.util.HashSet)

Example 19 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.

the class AbstractParsedStmt method simplifierForSubquery.

/**
     * Verify if a subquery can be replaced with a direct select from table(s)
     * @param subquery
     * @return TRUE/FALSE
     */
private StmtTargetTableScan simplifierForSubquery(AbstractParsedStmt subquery) {
    // Must be a SELECT statement (not a SET operation)
    if (!(subquery instanceof ParsedSelectStmt)) {
        return null;
    }
    ParsedSelectStmt selectSubquery = (ParsedSelectStmt) subquery;
    // No aggregation and/or GROUP BY is allowed
    if (selectSubquery.hasAggregateOrGroupby()) {
        return null;
    }
    // No DISTINCT
    if (selectSubquery.hasAggregateDistinct()) {
        return null;
    }
    // No windowed aggregate functions like RANK.
    if (selectSubquery.hasWindowFunctionExpression()) {
        return null;
    }
    // No LIMIT/OFFSET
    if (selectSubquery.hasLimitOrOffset() || selectSubquery.hasLimitOrOffsetParameters()) {
        return null;
    }
    // Only SELECT from a single TARGET TABLE is allowed
    int tableCount = 0;
    StmtTargetTableScan simpler = null;
    for (Map.Entry<String, StmtTableScan> entry : selectSubquery.m_tableAliasMap.entrySet()) {
        if (entry.getKey().startsWith(AbstractParsedStmt.TEMP_TABLE_NAME)) {
            // This is an artificial table for a subquery expression
            continue;
        }
        if (++tableCount > 1) {
            return null;
        }
        // Only allow one TARGET TABLE, not a nested subquery.
        StmtTableScan scan = entry.getValue();
        if (scan instanceof StmtTargetTableScan) {
            simpler = (StmtTargetTableScan) scan;
        } else {
            return null;
        }
    }
    return simpler;
}
Also used : StmtTargetTableScan(org.voltdb.planner.parseinfo.StmtTargetTableScan) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) CatalogMap(org.voltdb.catalog.CatalogMap) Constraint(org.voltdb.catalog.Constraint) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan)

Example 20 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.

the class AbstractParsedStmt method addSubqueryToStmtCache.

/**
     * Add a sub-query to the statement cache.
     * @param subquery
     * @param tableAlias
     * @return the cache entry
     */
protected StmtSubqueryScan addSubqueryToStmtCache(AbstractParsedStmt subquery, String tableAlias) {
    assert (subquery != null);
    // generate a unique one for internal use.
    if (tableAlias == null) {
        tableAlias = AbstractParsedStmt.TEMP_TABLE_NAME + "_" + subquery.m_stmtId;
    }
    StmtSubqueryScan subqueryScan = new StmtSubqueryScan(subquery, tableAlias, m_stmtId);
    StmtTableScan prior = m_tableAliasMap.put(tableAlias, subqueryScan);
    assert (prior == null);
    return subqueryScan;
}
Also used : StmtSubqueryScan(org.voltdb.planner.parseinfo.StmtSubqueryScan) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan)

Aggregations

StmtTableScan (org.voltdb.planner.parseinfo.StmtTableScan)28 AbstractExpression (org.voltdb.expressions.AbstractExpression)16 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)9 Constraint (org.voltdb.catalog.Constraint)8 SchemaColumn (org.voltdb.plannodes.SchemaColumn)8 HashSet (java.util.HashSet)7 Table (org.voltdb.catalog.Table)7 StmtTargetTableScan (org.voltdb.planner.parseinfo.StmtTargetTableScan)7 ArrayList (java.util.ArrayList)6 Index (org.voltdb.catalog.Index)6 StmtSubqueryScan (org.voltdb.planner.parseinfo.StmtSubqueryScan)6 Set (java.util.Set)5 JSONException (org.json_voltpatches.JSONException)5 ColumnRef (org.voltdb.catalog.ColumnRef)5 ParameterValueExpression (org.voltdb.expressions.ParameterValueExpression)5 HashMap (java.util.HashMap)4 Column (org.voltdb.catalog.Column)4 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)4 TreeMap (java.util.TreeMap)3 ConstantValueExpression (org.voltdb.expressions.ConstantValueExpression)3