Search in sources :

Example 16 with ColumnRef

use of org.voltdb.catalog.ColumnRef 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 ColumnRef

use of org.voltdb.catalog.ColumnRef 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 18 with ColumnRef

use of org.voltdb.catalog.ColumnRef in project voltdb by VoltDB.

the class SwapTablesPlanNode method indexesCanBeSwapped.

/**
     * @param theIndex candidate match for otherIndex on the target table
     * @param otherIndex candidate match for theIndex on the other target table
     * @param candidateIndexSet set of otherTable indexes as yet unmatched
     */
private static boolean indexesCanBeSwapped(Index theIndex, Index otherIndex) {
    // Pairs of matching indexes must agree on type (int hash, etc.).
    if (theIndex.getType() != otherIndex.getType()) {
        return false;
    }
    // Pairs of matching indexes must agree whether they are (assume)unique.
    if (theIndex.getUnique() != otherIndex.getUnique() || theIndex.getAssumeunique() != otherIndex.getAssumeunique()) {
        return false;
    }
    // Pairs of matching indexes must agree whether they are partial
    // and if so, agree on the predicate.
    String thePredicateJSON = theIndex.getPredicatejson();
    String otherPredicateJSON = otherIndex.getPredicatejson();
    if (thePredicateJSON == null) {
        if (otherPredicateJSON != null) {
            return false;
        }
    } else if (!thePredicateJSON.equals(otherPredicateJSON)) {
        return false;
    }
    // Pairs of matching indexes must agree that they do or do not index
    // expressions and, if so, agree on the expressions.
    String theExprsJSON = theIndex.getExpressionsjson();
    String otherExprsJSON = otherIndex.getExpressionsjson();
    if (theExprsJSON == null) {
        if (otherExprsJSON != null) {
            return false;
        }
    } else if (!theExprsJSON.equals(otherExprsJSON)) {
        return false;
    }
    // Indexes must agree on the columns they are based on,
    // identifiable by the columns' order in the table.
    CatalogMap<ColumnRef> theColumns = theIndex.getColumns();
    int theColumnCount = theColumns.size();
    CatalogMap<ColumnRef> otherColumns = otherIndex.getColumns();
    if (theColumnCount != otherColumns.size()) {
        return false;
    }
    Iterator<ColumnRef> theColumnIterator = theColumns.iterator();
    Iterator<ColumnRef> otherColumnIterator = otherColumns.iterator();
    for (int ii = 0; ii < theColumnCount; ++ii) {
        int theColIndex = theColumnIterator.next().getColumn().getIndex();
        int otherColIndex = otherColumnIterator.next().getColumn().getIndex();
        if (theColIndex != otherColIndex) {
            return false;
        }
    }
    return true;
}
Also used : ColumnRef(org.voltdb.catalog.ColumnRef) Constraint(org.voltdb.catalog.Constraint)

Example 19 with ColumnRef

use of org.voltdb.catalog.ColumnRef in project voltdb by VoltDB.

the class SwapTablesPlanNode method diagnoseIndexMismatch.

/**
     * Give two strings, return a list of attributes that do not match
     * @param theIndex
     * @param otherIndex
     * @return list of attributes that do not match
     */
private List<String> diagnoseIndexMismatch(Index theIndex, Index otherIndex) {
    List<String> mismatchedAttrs = new ArrayList<>();
    // Pairs of matching indexes must agree on type (int hash, etc.).
    if (theIndex.getType() != otherIndex.getType()) {
        mismatchedAttrs.add("index type (hash vs tree)");
    }
    // Pairs of matching indexes must agree whether they are (assume)unique.
    if (theIndex.getUnique() != otherIndex.getUnique() || theIndex.getAssumeunique() != otherIndex.getAssumeunique()) {
        mismatchedAttrs.add("UNIQUE attribute");
    }
    // Pairs of matching indexes must agree whether they are partial
    // and if so, agree on the predicate.
    String thePredicateJSON = theIndex.getPredicatejson();
    String otherPredicateJSON = otherIndex.getPredicatejson();
    if (thePredicateJSON == null) {
        if (otherPredicateJSON != null) {
            mismatchedAttrs.add("WHERE predicate");
        }
    } else if (!thePredicateJSON.equals(otherPredicateJSON)) {
        mismatchedAttrs.add("WHERE predicate");
    }
    // Pairs of matching indexes must agree that they do or do not index
    // expressions and, if so, agree on the expressions.
    String theExprsJSON = theIndex.getExpressionsjson();
    String otherExprsJSON = otherIndex.getExpressionsjson();
    if (theExprsJSON == null) {
        if (otherExprsJSON != null) {
            mismatchedAttrs.add("indexed expression");
        }
    } else if (!theExprsJSON.equals(otherExprsJSON)) {
        mismatchedAttrs.add("indexed expression");
    }
    // Indexes must agree on the columns they are based on,
    // identifiable by the columns' order in the table.
    CatalogMap<ColumnRef> theColumns = theIndex.getColumns();
    int theColumnCount = theColumns.size();
    CatalogMap<ColumnRef> otherColumns = otherIndex.getColumns();
    if (theColumnCount != otherColumns.size()) {
        mismatchedAttrs.add("indexed expression");
    }
    Iterator<ColumnRef> theColumnIterator = theColumns.iterator();
    Iterator<ColumnRef> otherColumnIterator = otherColumns.iterator();
    for (int ii = 0; ii < theColumnCount; ++ii) {
        int theColIndex = theColumnIterator.next().getColumn().getIndex();
        int otherColIndex = otherColumnIterator.next().getColumn().getIndex();
        if (theColIndex != otherColIndex) {
            mismatchedAttrs.add("indexed expression");
        }
    }
    return mismatchedAttrs;
}
Also used : ArrayList(java.util.ArrayList) ColumnRef(org.voltdb.catalog.ColumnRef) Constraint(org.voltdb.catalog.Constraint)

Example 20 with ColumnRef

use of org.voltdb.catalog.ColumnRef in project voltdb by VoltDB.

the class IndexCountPlanNode method explainPlanForNode.

@Override
protected String explainPlanForNode(String indent) {
    assert (m_catalogIndex != null);
    int indexSize = CatalogUtil.getCatalogIndexSize(m_catalogIndex);
    int searchkeySize = m_searchkeyExpressions.size();
    int endkeySize = m_endkeyExpressions.size();
    int keySize = Math.max(searchkeySize, endkeySize);
    String scanType = "tree-counter";
    String cover = "covering";
    if (indexSize > keySize)
        cover = String.format("%d/%d cols", keySize, indexSize);
    String usageInfo = String.format("(%s %s)", scanType, cover);
    String[] asIndexed = new String[indexSize];
    // they beat an NPE.
    for (int ii = 0; ii < keySize; ++ii) {
        asIndexed[ii] = "(index key " + ii + ")";
    }
    String jsonExpr = m_catalogIndex.getExpressionsjson();
    // if this is a pure-column index...
    if (jsonExpr.isEmpty()) {
        // grab the short names of the indexed columns in use.
        for (ColumnRef cref : m_catalogIndex.getColumns()) {
            Column col = cref.getColumn();
            asIndexed[cref.getIndex()] = col.getName();
        }
    } else {
        try {
            List<AbstractExpression> indexExpressions = AbstractExpression.fromJSONArrayString(jsonExpr, m_tableScan);
            int ii = 0;
            for (AbstractExpression ae : indexExpressions) {
                asIndexed[ii++] = ae.explain(m_targetTableName);
            }
        } catch (JSONException e) {
        // If something unexpected went wrong,
        // just fall back on the positional key labels.
        }
    }
    // "(event_type = 1 AND event_start > x.start_time)"
    if (searchkeySize > 0) {
        String start = explainKeys(asIndexed, m_searchkeyExpressions, m_targetTableName, m_lookupType, m_compareNotDistinct);
        usageInfo += "\n" + indent + " count matches from " + start;
    }
    if (endkeySize > 0) {
        String end = explainKeys(asIndexed, m_endkeyExpressions, m_targetTableName, m_endType, m_compareNotDistinct);
        usageInfo += "\n" + indent + " count matches to " + end;
    }
    if (m_skip_null_predicate != null) {
        String predicate = m_skip_null_predicate.explain(m_targetTableName);
        usageInfo += "\n" + indent + " discounting rows where " + predicate;
    }
    // Describe the table name and either a user-provided name of the index or
    // its user-specified role ("primary key").
    String retval = "INDEX COUNT of \"" + m_targetTableName + "\"";
    String indexDescription = " using \"" + m_targetIndexName + "\"";
    // Replace ugly system-generated index name with a description of its user-specified role.
    if (m_targetIndexName.startsWith(HSQLInterface.AUTO_GEN_PRIMARY_KEY_PREFIX) || m_targetIndexName.startsWith(HSQLInterface.AUTO_GEN_NAMED_CONSTRAINT_IDX) || m_targetIndexName.equals(HSQLInterface.AUTO_GEN_MATVIEW_IDX)) {
        indexDescription = " using its primary key index";
    }
    // Bring all the pieces together describing the index, how it is scanned,
    // and whatever extra filter processing is done to the result.
    retval += indexDescription;
    retval += usageInfo;
    return retval;
}
Also used : AbstractExpression(org.voltdb.expressions.AbstractExpression) Column(org.voltdb.catalog.Column) JSONException(org.json_voltpatches.JSONException) ColumnRef(org.voltdb.catalog.ColumnRef)

Aggregations

ColumnRef (org.voltdb.catalog.ColumnRef)29 AbstractExpression (org.voltdb.expressions.AbstractExpression)19 Column (org.voltdb.catalog.Column)18 Constraint (org.voltdb.catalog.Constraint)16 ArrayList (java.util.ArrayList)14 JSONException (org.json_voltpatches.JSONException)14 Index (org.voltdb.catalog.Index)9 Table (org.voltdb.catalog.Table)9 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)9 HashSet (java.util.HashSet)5 StmtTableScan (org.voltdb.planner.parseinfo.StmtTableScan)5 StmtTargetTableScan (org.voltdb.planner.parseinfo.StmtTargetTableScan)4 SchemaColumn (org.voltdb.plannodes.SchemaColumn)4 VoltType (org.voltdb.VoltType)3 VoltCompilerException (org.voltdb.compiler.VoltCompiler.VoltCompilerException)3 ConstantValueExpression (org.voltdb.expressions.ConstantValueExpression)3 HashMap (java.util.HashMap)2 Set (java.util.Set)2 VoltXMLElement (org.hsqldb_voltpatches.VoltXMLElement)2 Procedure (org.voltdb.catalog.Procedure)2