Search in sources :

Example 11 with ConstantValueExpression

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;
                }
            }
        }
    }
}
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 12 with ConstantValueExpression

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;
}
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 13 with ConstantValueExpression

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);
    }
}
Also used : TupleAddressExpression(org.voltdb.expressions.TupleAddressExpression) TupleValueExpression(org.voltdb.expressions.TupleValueExpression) ConstantValueExpression(org.voltdb.expressions.ConstantValueExpression) OperatorExpression(org.voltdb.expressions.OperatorExpression) ParameterValueExpression(org.voltdb.expressions.ParameterValueExpression)

Example 14 with ConstantValueExpression

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);
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) ConstantValueExpression(org.voltdb.expressions.ConstantValueExpression) ArrayList(java.util.ArrayList) ParameterValueExpression(org.voltdb.expressions.ParameterValueExpression)

Example 15 with ConstantValueExpression

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;
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) ConstantValueExpression(org.voltdb.expressions.ConstantValueExpression) SchemaColumn(org.voltdb.plannodes.SchemaColumn) ParameterValueExpression(org.voltdb.expressions.ParameterValueExpression) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan)

Aggregations

ConstantValueExpression (org.voltdb.expressions.ConstantValueExpression)15 AbstractExpression (org.voltdb.expressions.AbstractExpression)12 ParameterValueExpression (org.voltdb.expressions.ParameterValueExpression)8 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)7 ArrayList (java.util.ArrayList)5 HashSet (java.util.HashSet)3 Set (java.util.Set)3 VoltType (org.voltdb.VoltType)3 ColumnRef (org.voltdb.catalog.ColumnRef)3 StmtTableScan (org.voltdb.planner.parseinfo.StmtTableScan)3 SchemaColumn (org.voltdb.plannodes.SchemaColumn)3 JSONException (org.json_voltpatches.JSONException)2 Column (org.voltdb.catalog.Column)2 Constraint (org.voltdb.catalog.Constraint)2 Index (org.voltdb.catalog.Index)2 Table (org.voltdb.catalog.Table)2 OperatorExpression (org.voltdb.expressions.OperatorExpression)2 HashMap (java.util.HashMap)1 AggregateExpression (org.voltdb.expressions.AggregateExpression)1 ComparisonExpression (org.voltdb.expressions.ComparisonExpression)1