Search in sources :

Example 11 with TupleValueExpression

use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.

the class TestSelfJoins method testIndexedSelfJoin.

public void testIndexedSelfJoin() {
    AbstractPlanNode.enableVerboseExplainForDebugging();
    IndexScanPlanNode c;
    AbstractPlanNode apn;
    AbstractPlanNode pn;
    NestLoopIndexPlanNode nlij;
    List<AbstractExpression> searchKeys;
    // SELF JOIN using two different indexes on the same table
    // sometimes with a surviving sort ordering that supports GROUP BY and/or ORDER BY.
    apn = compile("select * FROM R2 A, R2 B WHERE A.A = B.A AND B.C > 1 ORDER BY B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    // Some day, the wasteful projection node will not be here to skip.
    pn = apn.getChild(0).getChild(0);
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertNull(c.getPredicate());
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
    apn = compile("select * FROM R2 A, R2 B WHERE A.A = B.A AND B.C > 1 ORDER BY B.A, B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    // Some day, the wasteful projection node will not be here to skip.
    pn = apn.getChild(0).getChild(0);
    assertTrue(pn instanceof OrderByPlanNode);
    pn = pn.getChild(0);
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertNull(c.getPredicate());
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
    apn = compile("select * FROM R2 A, R2 B WHERE A.A = B.A AND B.A > 1 ORDER BY B.A, B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    // Some day, the wasteful projection node will not be here to skip.
    pn = apn.getChild(0).getChild(0);
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    assertTrue(nlij.getChild(0) instanceof IndexScanPlanNode);
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
    apn = compile("select B.C, MAX(A.C) FROM R2 A, R2 B WHERE A.A = B.A AND B.C > 1 GROUP BY B.C ORDER BY B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    // Some day, the wasteful projection node will not be here to skip.
    pn = apn.getChild(0);
    assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertNull(c.getPredicate());
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
    apn = compile("select B.C, B.A FROM R2 A, R2 B WHERE A.A = B.A AND B.C > 1 GROUP BY B.A, B.C ORDER BY B.A, B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    // Some day, the wasteful projection node will not be here to skip.
    pn = apn.getChild(0).getChild(0);
    assertTrue(pn instanceof OrderByPlanNode);
    pn = pn.getChild(0);
    assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertNull(c.getPredicate());
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
    apn = compile("select B.C, B.A FROM R2 A, R2 B WHERE A.A = B.A AND B.A > 1 GROUP BY B.A, B.C ORDER BY B.A, B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    pn = apn.getChild(0);
    assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    assertTrue(nlij.getChild(0) instanceof IndexScanPlanNode);
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
    // Here's a case that can't be optimized because it purposely uses the "wrong" column
    // in the GROUP BY and ORDER BY.
    apn = compile("select B.C FROM R2 A, R2 B WHERE B.A = A.A AND B.C > 1 GROUP BY A.A, B.C ORDER BY A.A, B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    // Complex ORDER BY case: GROUP BY column that is not in the display column list
    pn = apn.getChild(0);
    assertTrue(pn instanceof ProjectionPlanNode);
    pn = pn.getChild(0);
    assertTrue(pn instanceof OrderByPlanNode);
    pn = pn.getChild(0);
    assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertNull(c.getPredicate());
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
    // Here's a case that can't be optimized because it purposely uses the "wrong" column
    // in the GROUP BY and ORDER BY.
    apn = compile("select B.C FROM R2 A, R2 B WHERE B.A = A.A AND B.C > 1 GROUP BY A.A, B.C ORDER BY B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    // Project-first case: GROUP BY column that is not in the order by or the display column list
    pn = apn.getChild(0);
    assertTrue(pn instanceof OrderByPlanNode);
    pn = pn.getChild(0);
    //TODO: This represents a missed optimization.
    // The projection could have been inlined.
    assertTrue(pn instanceof ProjectionPlanNode);
    pn = pn.getChild(0);
    assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertNull(c.getPredicate());
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
    // This variant shows that the GROUP BY can be a permutation of the sort order
    // without messing up the optimization
    apn = compile("select B.C, B.A FROM R2 A, R2 B WHERE A.A = B.A AND B.A > 1 GROUP BY B.C, B.A ORDER BY B.A, B.C");
    //* for debug */ System.out.println(apn.toExplainPlanString());
    // Some day, the wasteful projection node will not be here to skip.
    pn = apn.getChild(0);
    assertNotNull(AggregatePlanNode.getInlineAggregationNode(pn));
    assertTrue(pn instanceof NestLoopIndexPlanNode);
    nlij = (NestLoopIndexPlanNode) pn;
    assertNull(nlij.getPreJoinPredicate());
    assertNull(nlij.getJoinPredicate());
    assertNull(nlij.getWherePredicate());
    assertEquals(1, nlij.getChildCount());
    assertTrue(nlij.getChild(0) instanceof IndexScanPlanNode);
    c = (IndexScanPlanNode) nlij.getChild(0);
    assertEquals(IndexLookupType.GT, c.getLookupType());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof ConstantValueExpression);
    c = (IndexScanPlanNode) nlij.getInlinePlanNode(PlanNodeType.INDEXSCAN);
    assertEquals(IndexLookupType.GTE, c.getLookupType());
    assertNull(c.getPredicate());
    searchKeys = c.getSearchKeyExpressions();
    assertEquals(1, searchKeys.size());
    assertTrue(searchKeys.get(0) instanceof TupleValueExpression);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) TupleValueExpression(org.voltdb.expressions.TupleValueExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) OrderByPlanNode(org.voltdb.plannodes.OrderByPlanNode) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) ConstantValueExpression(org.voltdb.expressions.ConstantValueExpression) NestLoopIndexPlanNode(org.voltdb.plannodes.NestLoopIndexPlanNode) ProjectionPlanNode(org.voltdb.plannodes.ProjectionPlanNode)

Example 12 with TupleValueExpression

use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.

the class TestWindowedFunctions method validateTVEs.

public void validateTVEs(NodeSchema input_schema, WindowFunctionPlanNode pbPlanNode, boolean waiveAliasMatch) {
    List<AbstractExpression> tves = new ArrayList<>();
    for (AbstractExpression ae : pbPlanNode.getPartitionByExpressions()) {
        tves.addAll(ae.findAllTupleValueSubexpressions());
    }
    List<SchemaColumn> columns = input_schema.getColumns();
    for (AbstractExpression ae : tves) {
        TupleValueExpression tve = (TupleValueExpression) ae;
        assertTrue(0 <= tve.getColumnIndex() && tve.getColumnIndex() < columns.size());
        SchemaColumn col = columns.get(tve.getColumnIndex());
        String msg = String.format("TVE %d, COL %s: ", tve.getColumnIndex(), col.getColumnName() + ":" + col.getColumnAlias());
        assertEquals(msg, col.getTableName(), tve.getTableName());
        assertEquals(msg, col.getTableAlias(), tve.getTableAlias());
        assertEquals(msg, col.getColumnName(), tve.getColumnName());
        if (!waiveAliasMatch) {
            assertEquals(msg, col.getColumnAlias(), tve.getColumnAlias());
        }
    }
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) ArrayList(java.util.ArrayList) SchemaColumn(org.voltdb.plannodes.SchemaColumn)

Example 13 with TupleValueExpression

use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.

the class DDLCompiler method addIndexToCatalog.

private static void addIndexToCatalog(Database db, Table table, VoltXMLElement node, Map<String, String> indexReplacementMap, HashMap<String, Index> indexMap, HashMap<String, Column> columnMap, VoltCompiler compiler) throws VoltCompilerException {
    assert node.name.equals("index");
    String name = node.attributes.get("name");
    boolean unique = Boolean.parseBoolean(node.attributes.get("unique"));
    boolean assumeUnique = Boolean.parseBoolean(node.attributes.get("assumeunique"));
    AbstractParsedStmt dummy = new ParsedSelectStmt(null, db);
    dummy.setDDLIndexedTable(table);
    StringBuffer msg = new StringBuffer(String.format("Index \"%s\" ", name));
    // "parse" the expression trees for an expression-based index (vs. a simple column value index)
    List<AbstractExpression> exprs = null;
    // "parse" the WHERE expression for partial index if any
    AbstractExpression predicate = null;
    // Some expressions have special validation in indices.  Not all the expression
    // can be indexed. We scan for result type at first here and block those which
    // can't be indexed like boolean, geo ... We gather rest of expression into
    // checkExpressions list.  We will check on them all at once.
    List<AbstractExpression> checkExpressions = new ArrayList<>();
    for (VoltXMLElement subNode : node.children) {
        if (subNode.name.equals("exprs")) {
            exprs = new ArrayList<>();
            for (VoltXMLElement exprNode : subNode.children) {
                AbstractExpression expr = dummy.parseExpressionTree(exprNode);
                expr.resolveForTable(table);
                expr.finalizeValueTypes();
                // string will be populated with an expression's details when
                // its value type is not indexable
                StringBuffer exprMsg = new StringBuffer();
                if (!expr.isValueTypeIndexable(exprMsg)) {
                    // indexing on expression with boolean result is not supported.
                    throw compiler.new VoltCompilerException("Cannot create index \"" + name + "\" because it contains " + exprMsg + ", which is not supported.");
                }
                if ((unique || assumeUnique) && !expr.isValueTypeUniqueIndexable(exprMsg)) {
                    // indexing on expression with boolean result is not supported.
                    throw compiler.new VoltCompilerException("Cannot create unique index \"" + name + "\" because it contains " + exprMsg + ", which is not supported.");
                }
                // rest of the validity guards will be evaluated after collecting all the expressions.
                checkExpressions.add(expr);
                exprs.add(expr);
            }
        } else if (subNode.name.equals("predicate")) {
            assert (subNode.children.size() == 1);
            VoltXMLElement predicateXML = subNode.children.get(0);
            assert (predicateXML != null);
            predicate = buildPartialIndexPredicate(dummy, name, predicateXML, table, compiler);
        }
    }
    // Check all the subexpressions we gathered up.
    if (!AbstractExpression.validateExprsForIndexesAndMVs(checkExpressions, msg)) {
        // The error message will be in the StringBuffer msg.
        throw compiler.new VoltCompilerException(msg.toString());
    }
    String colList = node.attributes.get("columns");
    String[] colNames = colList.split(",");
    Column[] columns = new Column[colNames.length];
    boolean has_nonint_col = false;
    boolean has_geo_col = false;
    String nonint_col_name = null;
    for (int i = 0; i < colNames.length; i++) {
        columns[i] = columnMap.get(colNames[i]);
        if (columns[i] == null) {
            return;
        }
    }
    UnsafeOperatorsForDDL unsafeOps = new UnsafeOperatorsForDDL();
    if (exprs == null) {
        for (int i = 0; i < colNames.length; i++) {
            VoltType colType = VoltType.get((byte) columns[i].getType());
            if (!colType.isIndexable()) {
                String emsg = "Cannot create index \"" + name + "\" because " + colType.getName() + " values are not currently supported as index keys: \"" + colNames[i] + "\"";
                throw compiler.new VoltCompilerException(emsg);
            }
            if ((unique || assumeUnique) && !colType.isUniqueIndexable()) {
                String emsg = "Cannot create index \"" + name + "\" because " + colType.getName() + " values are not currently supported as unique index keys: \"" + colNames[i] + "\"";
                throw compiler.new VoltCompilerException(emsg);
            }
            if (!colType.isBackendIntegerType()) {
                has_nonint_col = true;
                nonint_col_name = colNames[i];
                has_geo_col = colType.equals(VoltType.GEOGRAPHY);
                if (has_geo_col && colNames.length > 1) {
                    String emsg = "Cannot create index \"" + name + "\" because " + colType.getName() + " values must be the only component of an index key: \"" + nonint_col_name + "\"";
                    throw compiler.new VoltCompilerException(emsg);
                }
            }
        }
    } else {
        for (AbstractExpression expression : exprs) {
            VoltType colType = expression.getValueType();
            if (!colType.isIndexable()) {
                String emsg = "Cannot create index \"" + name + "\" because " + colType.getName() + " valued expressions are not currently supported as index keys.";
                throw compiler.new VoltCompilerException(emsg);
            }
            if ((unique || assumeUnique) && !colType.isUniqueIndexable()) {
                String emsg = "Cannot create index \"" + name + "\" because " + colType.getName() + " valued expressions are not currently supported as unique index keys.";
                throw compiler.new VoltCompilerException(emsg);
            }
            if (!colType.isBackendIntegerType()) {
                has_nonint_col = true;
                nonint_col_name = "<expression>";
                has_geo_col = colType.equals(VoltType.GEOGRAPHY);
                if (has_geo_col) {
                    if (exprs.size() > 1) {
                        String emsg = "Cannot create index \"" + name + "\" because " + colType.getName() + " values must be the only component of an index key.";
                        throw compiler.new VoltCompilerException(emsg);
                    } else if (!(expression instanceof TupleValueExpression)) {
                        String emsg = "Cannot create index \"" + name + "\" because " + colType.getName() + " expressions must be simple column expressions.";
                        throw compiler.new VoltCompilerException(emsg);
                    }
                }
            }
            expression.findUnsafeOperatorsForDDL(unsafeOps);
        }
    }
    Index index = table.getIndexes().add(name);
    index.setCountable(false);
    index.setIssafewithnonemptysources(!unsafeOps.isUnsafe());
    // Set the index type.  It will be one of:
    // - Covering cell index (geo index for CONTAINS predicates)
    // - HASH index (set in HSQL because "hash" is in the name of the
    //   constraint or the index
    // - TREE index, which is the default
    boolean isHashIndex = node.attributes.get("ishashindex").equals("true");
    if (has_geo_col) {
        index.setType(IndexType.COVERING_CELL_INDEX.getValue());
    } else if (isHashIndex) {
        // warn user that hash index will be deprecated
        compiler.addWarn("Hash indexes are deprecated. In a future release, VoltDB will only support tree indexes, even if the index name contains the string \"hash\"");
        // make the index a hash.
        if (has_nonint_col) {
            String emsg = "Index " + name + " in table " + table.getTypeName() + " uses a non-hashable column " + nonint_col_name;
            throw compiler.new VoltCompilerException(emsg);
        }
        index.setType(IndexType.HASH_TABLE.getValue());
    } else {
        index.setType(IndexType.BALANCED_TREE.getValue());
        index.setCountable(true);
    }
    // but they still represent the columns that will trigger an index update when their values change.
    for (int i = 0; i < columns.length; i++) {
        ColumnRef cref = index.getColumns().add(columns[i].getTypeName());
        cref.setColumn(columns[i]);
        cref.setIndex(i);
    }
    if (exprs != null) {
        try {
            index.setExpressionsjson(convertToJSONArray(exprs));
        } catch (JSONException e) {
            throw compiler.new VoltCompilerException("Unexpected error serializing non-column expressions for index '" + name + "' on type '" + table.getTypeName() + "': " + e.toString());
        }
    }
    index.setUnique(unique);
    if (assumeUnique) {
        index.setUnique(true);
    }
    index.setAssumeunique(assumeUnique);
    if (predicate != null) {
        try {
            index.setPredicatejson(convertToJSONObject(predicate));
        } catch (JSONException e) {
            throw compiler.new VoltCompilerException("Unexpected error serializing predicate for partial index '" + name + "' on type '" + table.getTypeName() + "': " + e.toString());
        }
    }
    // will make two indexes different
    for (Index existingIndex : table.getIndexes()) {
        // skip thineself
        if (existingIndex == index) {
            continue;
        }
        if (indexesAreDups(existingIndex, index)) {
            // replace any constraints using one index with the other
            //for () TODO
            // get ready for replacements from constraints created later
            indexReplacementMap.put(index.getTypeName(), existingIndex.getTypeName());
            // if the index is a user-named index...
            if (index.getTypeName().startsWith(HSQLInterface.AUTO_GEN_PREFIX) == false) {
                // on dup-detection, add a warning but don't fail
                String emsg = String.format("Dropping index %s on table %s because it duplicates index %s.", index.getTypeName(), table.getTypeName(), existingIndex.getTypeName());
                compiler.addWarn(emsg);
            }
            // drop the index and GTFO
            table.getIndexes().delete(index.getTypeName());
            return;
        }
    }
    String smsg = "Created index: " + name + " on table: " + table.getTypeName() + " of type: " + IndexType.get(index.getType()).name();
    compiler.addInfo(smsg);
    indexMap.put(name, index);
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) ArrayList(java.util.ArrayList) JSONException(org.json_voltpatches.JSONException) Index(org.voltdb.catalog.Index) VoltXMLElement(org.hsqldb_voltpatches.VoltXMLElement) AbstractParsedStmt(org.voltdb.planner.AbstractParsedStmt) Constraint(org.voltdb.catalog.Constraint) UnsafeOperatorsForDDL(org.voltdb.expressions.AbstractExpression.UnsafeOperatorsForDDL) AbstractExpression(org.voltdb.expressions.AbstractExpression) Column(org.voltdb.catalog.Column) VoltType(org.voltdb.VoltType) ParsedSelectStmt(org.voltdb.planner.ParsedSelectStmt) ColumnRef(org.voltdb.catalog.ColumnRef) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException)

Example 14 with TupleValueExpression

use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.

the class MaterializedViewProcessor method isGroupbyMatchingIndex.

private static boolean isGroupbyMatchingIndex(MatViewIndexMatchingGroupby matchingCase, List<ColumnRef> groupbyColRefs, List<AbstractExpression> groupbyExprs, List<ColumnRef> indexedColRefs, List<AbstractExpression> indexedExprs, List<Column> srcColumnArray) {
    // Compare group-by columns/expressions for different cases
    switch(matchingCase) {
        case GB_COL_IDX_COL:
            for (int i = 0; i < groupbyColRefs.size(); ++i) {
                int groupbyColIndex = groupbyColRefs.get(i).getColumn().getIndex();
                int indexedColIndex = indexedColRefs.get(i).getColumn().getIndex();
                if (groupbyColIndex != indexedColIndex) {
                    return false;
                }
            }
            break;
        case GB_COL_IDX_EXP:
            for (int i = 0; i < groupbyColRefs.size(); ++i) {
                AbstractExpression indexedExpr = indexedExprs.get(i);
                if (!(indexedExpr instanceof TupleValueExpression)) {
                    // Group-by columns are all simple columns, so indexedExpr must be tve.
                    return false;
                }
                int indexedColIdx = ((TupleValueExpression) indexedExpr).getColumnIndex();
                Column indexedColumn = srcColumnArray.get(indexedColIdx);
                Column groupbyColumn = groupbyColRefs.get(i).getColumn();
                if (!indexedColumn.equals(groupbyColumn)) {
                    return false;
                }
            }
            break;
        case GB_EXP_IDX_EXP:
            for (int i = 0; i < groupbyExprs.size(); ++i) {
                if (!indexedExprs.get(i).equals(groupbyExprs.get(i))) {
                    return false;
                }
            }
            break;
        default:
            assert (false);
            // invalid option
            return false;
    }
    // group-by columns/expressions are matched with the corresponding index
    return true;
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) Column(org.voltdb.catalog.Column) Constraint(org.voltdb.catalog.Constraint)

Example 15 with TupleValueExpression

use of org.voltdb.expressions.TupleValueExpression in project voltdb by VoltDB.

the class MaterializedViewProcessor method setGroupedTablePartitionColumn.

private void setGroupedTablePartitionColumn(MaterializedViewInfo mvi, Column partitionColumn) throws VoltCompilerException {
    // A view of a replicated table is replicated.
    // A view of a partitioned table is partitioned -- regardless of whether it has a partition key
    // -- it certainly isn't replicated!
    // If the partitioning column is grouped, its counterpart is the partitioning column of the view table.
    // Otherwise, the view table just doesn't have a partitioning column
    // -- it is seemingly randomly distributed,
    // and its grouped columns are only locally unique but not globally unique.
    Table destTable = mvi.getDest();
    // Get the grouped columns in "index" order.
    // This order corresponds to the iteration order of the MaterializedViewInfo's group by columns.
    List<Column> destColumnArray = CatalogUtil.getSortedCatalogItems(destTable.getColumns(), "index");
    // Note getTypeName gets the column name -- go figure.
    String partitionColName = partitionColumn.getTypeName();
    if (mvi.getGroupbycols().size() > 0) {
        int index = 0;
        for (ColumnRef cref : CatalogUtil.getSortedCatalogItems(mvi.getGroupbycols(), "index")) {
            Column srcCol = cref.getColumn();
            if (srcCol.getName().equals(partitionColName)) {
                Column destCol = destColumnArray.get(index);
                destTable.setPartitioncolumn(destCol);
                return;
            }
            ++index;
        }
    } else {
        String complexGroupbyJson = mvi.getGroupbyexpressionsjson();
        if (complexGroupbyJson.length() > 0) {
            int partitionColIndex = partitionColumn.getIndex();
            List<AbstractExpression> mvComplexGroupbyCols = null;
            try {
                mvComplexGroupbyCols = AbstractExpression.fromJSONArrayString(complexGroupbyJson, null);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            int index = 0;
            for (AbstractExpression expr : mvComplexGroupbyCols) {
                if (expr instanceof TupleValueExpression) {
                    TupleValueExpression tve = (TupleValueExpression) expr;
                    if (tve.getColumnIndex() == partitionColIndex) {
                        Column destCol = destColumnArray.get(index);
                        destTable.setPartitioncolumn(destCol);
                        return;
                    }
                }
                ++index;
            }
        }
    }
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) Table(org.voltdb.catalog.Table) AbstractExpression(org.voltdb.expressions.AbstractExpression) Column(org.voltdb.catalog.Column) JSONException(org.json_voltpatches.JSONException) ColumnRef(org.voltdb.catalog.ColumnRef) Constraint(org.voltdb.catalog.Constraint)

Aggregations

TupleValueExpression (org.voltdb.expressions.TupleValueExpression)83 AbstractExpression (org.voltdb.expressions.AbstractExpression)59 SchemaColumn (org.voltdb.plannodes.SchemaColumn)19 Column (org.voltdb.catalog.Column)17 ArrayList (java.util.ArrayList)16 HashSet (java.util.HashSet)14 Constraint (org.voltdb.catalog.Constraint)13 Table (org.voltdb.catalog.Table)10 ColumnRef (org.voltdb.catalog.ColumnRef)9 ParameterValueExpression (org.voltdb.expressions.ParameterValueExpression)9 StmtTableScan (org.voltdb.planner.parseinfo.StmtTableScan)9 JSONException (org.json_voltpatches.JSONException)8 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)8 NodeSchema (org.voltdb.plannodes.NodeSchema)8 ConstantValueExpression (org.voltdb.expressions.ConstantValueExpression)7 VoltXMLElement (org.hsqldb_voltpatches.VoltXMLElement)6 Set (java.util.Set)5 Index (org.voltdb.catalog.Index)5 StmtTargetTableScan (org.voltdb.planner.parseinfo.StmtTargetTableScan)5 ProjectionPlanNode (org.voltdb.plannodes.ProjectionPlanNode)5