Search in sources :

Example 21 with ExpressionType

use of org.voltdb.types.ExpressionType in project voltdb by VoltDB.

the class ParsedSelectStmt method verifyWindowFunctionExpressions.

/**
     * Verify the validity of the windowed expressions.
     *
     * @return
     */
private void verifyWindowFunctionExpressions() {
    // Check for windowed expressions.
    if (m_windowFunctionExpressions.size() > 0) {
        if (m_windowFunctionExpressions.size() > 1) {
            throw new PlanningErrorException("Only one windowed function call may appear in a selection list.");
        }
        if (m_hasAggregateExpression) {
            throw new PlanningErrorException("Use of window functions (in an OVER clause) isn't supported with other aggregate functions on the SELECT list.");
        }
        if (m_windowFunctionExpressions.get(0).hasSubqueryArgs()) {
            throw new PlanningErrorException("Window function calls with subquery expression arguments are not allowed.");
        }
        //
        // This could be an if statement, but I think it's better to
        // leave this as a pattern in case we decide to implement more
        // legality conditions for other windowed operators.
        //
        WindowFunctionExpression windowFunctionExpression = m_windowFunctionExpressions.get(0);
        List<AbstractExpression> orderByExpressions = windowFunctionExpression.getOrderByExpressions();
        ExpressionType exprType = windowFunctionExpression.getExpressionType();
        String aggName = exprType.symbol().toUpperCase();
        switch(exprType) {
            case AGGREGATE_WINDOWED_RANK:
            case AGGREGATE_WINDOWED_DENSE_RANK:
                if (orderByExpressions.size() == 0) {
                    throw new PlanningErrorException("Windowed " + aggName + " function call expressions require an ORDER BY specification.");
                }
                VoltType valType = orderByExpressions.get(0).getValueType();
                assert (valType != null);
                if (!valType.isAnyIntegerType() && (valType != VoltType.TIMESTAMP)) {
                    throw new PlanningErrorException("Windowed function call expressions can have only integer or TIMESTAMP value types in the ORDER BY expression of their window.");
                }
                break;
            case AGGREGATE_WINDOWED_COUNT:
                if (windowFunctionExpression.getAggregateArguments().size() > 1) {
                    throw new PlanningErrorException(String.format("Windowed COUNT must have either exactly one argument or else a star for an argument"));
                }
                // Any type is ok, so we won't inspect the type.
                break;
            case AGGREGATE_WINDOWED_MAX:
            case AGGREGATE_WINDOWED_MIN:
                if (windowFunctionExpression.getAggregateArguments().size() != 1) {
                    throw new PlanningErrorException(String.format("Windowed %s must have exactly one argument", aggName));
                }
                // Any type is ok, so we won't inspect the type.
                break;
            case AGGREGATE_WINDOWED_SUM:
                if (windowFunctionExpression.getAggregateArguments().size() != 1) {
                    throw new PlanningErrorException(String.format("Windowed SUM must have exactly one numeric argument"));
                }
                AbstractExpression arg = windowFunctionExpression.getAggregateArguments().get(0);
                VoltType vt = arg.getValueType();
                assert (vt != null);
                if (!vt.isNumber()) {
                    throw new PlanningErrorException("Windowed SUM must have exactly one numeric argument");
                }
                break;
            default:
                {
                    String opName = (exprType == null) ? "NULL" : exprType.symbol();
                    throw new PlanningErrorException("Unknown windowed aggregate function type: " + opName);
                }
        }
    }
}
Also used : AbstractExpression(org.voltdb.expressions.AbstractExpression) VoltType(org.voltdb.VoltType) WindowFunctionExpression(org.voltdb.expressions.WindowFunctionExpression) ExpressionType(org.voltdb.types.ExpressionType)

Example 22 with ExpressionType

use of org.voltdb.types.ExpressionType in project voltdb by VoltDB.

the class AggregatePlanNode method explainPlanForNode.

@Override
protected String explainPlanForNode(String indent) {
    StringBuilder sb = new StringBuilder();
    String optionalTableName = "*NO MATCH -- USE ALL TABLE NAMES*";
    String aggType = planNodeTypeToAggDescString(getPlanNodeType());
    sb.append(aggType + " AGGREGATION ops: ");
    String sep = "";
    int ii = 0;
    for (ExpressionType e : m_aggregateTypes) {
        sb.append(sep).append(e.symbol());
        sep = ", ";
        if (e != ExpressionType.AGGREGATE_COUNT_STAR) {
            if (m_aggregateDistinct.get(ii) == 1) {
                sb.append(" DISTINCT");
            }
            AbstractExpression ae = m_aggregateExpressions.get(ii);
            assert (ae != null);
            sb.append("(");
            sb.append(ae.explain(optionalTableName));
            sb.append(")");
        }
        ++ii;
    }
    if (m_prePredicate != null) {
        sb.append(" ONLY IF " + m_prePredicate.explain(optionalTableName));
    }
    if (m_postPredicate != null) {
        // HAVING is always defined WRT to the current outputSchema (NOT inputschema).
        // This might be a little surprising to the user
        // -- maybe we can find some better way to describe the TVEs, here.
        sb.append(" HAVING " + m_postPredicate.explain(AbstractParsedStmt.TEMP_TABLE_NAME));
    }
    return sb.toString();
}
Also used : AbstractExpression(org.voltdb.expressions.AbstractExpression) ExpressionType(org.voltdb.types.ExpressionType)

Example 23 with ExpressionType

use of org.voltdb.types.ExpressionType in project voltdb by VoltDB.

the class AbstractParsedStmt method parseAggregationExpression.

/**
     *
     * @param paramsById
     * @param exprNode
     * @return
     */
private AbstractExpression parseAggregationExpression(VoltXMLElement exprNode) {
    String type = exprNode.attributes.get("optype");
    ExpressionType exprType = ExpressionType.get(type);
    if (exprType == ExpressionType.INVALID) {
        throw new PlanningErrorException("Unsupported aggregation type '" + type + "'");
    }
    assert (exprNode.children.size() <= 1);
    // get the single required child node
    VoltXMLElement childExprNode = exprNode.children.get(0);
    assert (childExprNode != null);
    // recursively parse the child subtree -- could (in theory) be an operator or
    // a constant, column, or param value operand or null in the specific case of "COUNT(*)".
    AbstractExpression childExpr = parseExpressionNode(childExprNode);
    if (childExpr == null) {
        assert (exprType == ExpressionType.AGGREGATE_COUNT);
        exprType = ExpressionType.AGGREGATE_COUNT_STAR;
    }
    AggregateExpression expr = new AggregateExpression(exprType);
    expr.setLeft(childExpr);
    String node;
    if ((node = exprNode.attributes.get("distinct")) != null && Boolean.parseBoolean(node)) {
        expr.setDistinct();
    }
    if (m_aggregationList != null) {
        ExpressionUtil.finalizeValueTypes(expr);
        m_aggregationList.add(expr);
    }
    return expr;
}
Also used : AbstractExpression(org.voltdb.expressions.AbstractExpression) VoltXMLElement(org.hsqldb_voltpatches.VoltXMLElement) AggregateExpression(org.voltdb.expressions.AggregateExpression) ExpressionType(org.voltdb.types.ExpressionType)

Example 24 with ExpressionType

use of org.voltdb.types.ExpressionType in project voltdb by VoltDB.

the class AbstractParsedStmt method optimizeInExpressions.

/**
     * Perform various optimizations for IN/EXISTS subqueries if possible
     *
     * @param expr to optimize
     * @return optimized expression
     */
private AbstractExpression optimizeInExpressions(AbstractExpression expr) {
    ExpressionType exprType = expr.getExpressionType();
    if (ExpressionType.CONJUNCTION_AND == exprType || ExpressionType.CONJUNCTION_OR == exprType) {
        AbstractExpression optimizedLeft = optimizeInExpressions(expr.getLeft());
        expr.setLeft(optimizedLeft);
        AbstractExpression optimizedRight = optimizeInExpressions(expr.getRight());
        expr.setRight(optimizedRight);
        return expr;
    }
    if (ExpressionType.COMPARE_EQUAL != exprType) {
        return expr;
    }
    assert (expr instanceof ComparisonExpression);
    if (((ComparisonExpression) expr).getQuantifier() != QuantifierType.ANY) {
        return expr;
    }
    /*
         * Verify that an IN expression can be safely converted to an EXISTS one
         * IN (SELECT" forms e.g. "(A, B) IN (SELECT X, Y, FROM ...) =>
         * EXISTS (SELECT 42 FROM ... AND|WHERE|HAVING A=X AND|WHERE|HAVING B=Y)
         */
    AbstractExpression inColumns = expr.getLeft();
    if (inColumns instanceof SelectSubqueryExpression) {
        // (expression must return a single row at most)
        return expr;
    }
    // The right hand operand of the equality operation must be a SELECT statement
    AbstractExpression rightExpr = expr.getRight();
    if (!(rightExpr instanceof SelectSubqueryExpression)) {
        return expr;
    }
    SelectSubqueryExpression subqueryExpr = (SelectSubqueryExpression) rightExpr;
    AbstractParsedStmt subquery = subqueryExpr.getSubqueryStmt();
    if (!(subquery instanceof ParsedSelectStmt)) {
        return expr;
    }
    ParsedSelectStmt selectStmt = (ParsedSelectStmt) subquery;
    //      seems to require 1 match that has exactly 10-14 rows (matching or not) with lesser or equal values of Y.
    if (selectStmt.hasLimitOrOffset()) {
        return expr;
    }
    ParsedSelectStmt.rewriteInSubqueryAsExists(selectStmt, inColumns);
    subqueryExpr.resolveCorrelations();
    AbstractExpression existsExpr = new OperatorExpression();
    existsExpr.setExpressionType(ExpressionType.OPERATOR_EXISTS);
    existsExpr.setLeft(subqueryExpr);
    return optimizeExistsExpression(existsExpr);
}
Also used : ComparisonExpression(org.voltdb.expressions.ComparisonExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) OperatorExpression(org.voltdb.expressions.OperatorExpression) SelectSubqueryExpression(org.voltdb.expressions.SelectSubqueryExpression) ExpressionType(org.voltdb.types.ExpressionType)

Example 25 with ExpressionType

use of org.voltdb.types.ExpressionType in project voltdb by VoltDB.

the class AbstractParsedStmt method parseOperationExpression.

/**
     *
     * @param paramsById
     * @param exprNode
     * @return
     */
private AbstractExpression parseOperationExpression(VoltXMLElement exprNode) {
    String optype = exprNode.attributes.get("optype");
    ExpressionType exprType = ExpressionType.get(optype);
    AbstractExpression expr = null;
    if (exprType == ExpressionType.INVALID) {
        throw new PlanningErrorException("Unsupported operation type '" + optype + "'");
    }
    try {
        expr = exprType.getExpressionClass().newInstance();
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e.getMessage(), e);
    }
    expr.setExpressionType(exprType);
    if (exprType == ExpressionType.OPERATOR_CASE_WHEN || exprType == ExpressionType.OPERATOR_ALTERNATIVE) {
        String valueType = exprNode.attributes.get("valuetype");
        expr.setValueType(VoltType.typeFromString(valueType));
    }
    if (expr instanceof ComparisonExpression) {
        String opsubtype = exprNode.attributes.get("opsubtype");
        if (opsubtype != null) {
            QuantifierType quantifier = QuantifierType.get(opsubtype);
            if (quantifier != QuantifierType.NONE) {
                ((ComparisonExpression) expr).setQuantifier(quantifier);
            }
        }
    }
    // get the first (left) node that is an element
    VoltXMLElement leftExprNode = exprNode.children.get(0);
    assert (leftExprNode != null);
    // recursively parse the left subtree (could be another operator or
    // a constant/tuple/param value operand).
    AbstractExpression leftExpr = parseExpressionNode(leftExprNode);
    assert ((leftExpr != null) || (exprType == ExpressionType.AGGREGATE_COUNT));
    expr.setLeft(leftExpr);
    // get the second (right) node that is an element (might be null)
    VoltXMLElement rightExprNode = null;
    if (exprNode.children.size() > 1) {
        rightExprNode = exprNode.children.get(1);
    }
    if (expr.needsRightExpression()) {
        assert (rightExprNode != null);
        // recursively parse the right subtree
        AbstractExpression rightExpr = parseExpressionNode(rightExprNode);
        assert (rightExpr != null);
        expr.setRight(rightExpr);
    } else {
        assert (rightExprNode == null);
        if (exprType == ExpressionType.OPERATOR_CAST) {
            String valuetype = exprNode.attributes.get("valuetype");
            assert (valuetype != null);
            VoltType voltType = VoltType.typeFromString(valuetype);
            expr.setValueType(voltType);
            // We don't support parameterized casting, such as specifically to "VARCHAR(3)" vs. VARCHAR,
            // so assume max length for variable-length types (VARCHAR and VARBINARY).
            int size = voltType.getMaxLengthInBytes();
            expr.setValueSize(size);
        }
    }
    if (exprType == ExpressionType.COMPARE_EQUAL && QuantifierType.ANY == ((ComparisonExpression) expr).getQuantifier()) {
        // Break up UNION/INTERSECT (ALL) set ops into individual selects connected by
        // AND/OR operator
        // col IN ( queryA UNION queryB ) - > col IN (queryA) OR col IN (queryB)
        // col IN ( queryA INTERSECTS queryB ) - > col IN (queryA) AND col IN (queryB)
        expr = ParsedUnionStmt.breakUpSetOpSubquery(expr);
    } else if (exprType == ExpressionType.OPERATOR_EXISTS) {
        expr = optimizeExistsExpression(expr);
    }
    return expr;
}
Also used : ComparisonExpression(org.voltdb.expressions.ComparisonExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) VoltType(org.voltdb.VoltType) QuantifierType(org.voltdb.types.QuantifierType) VoltXMLElement(org.hsqldb_voltpatches.VoltXMLElement) ExpressionType(org.voltdb.types.ExpressionType) JSONException(org.json_voltpatches.JSONException) Constraint(org.voltdb.catalog.Constraint)

Aggregations

ExpressionType (org.voltdb.types.ExpressionType)30 AbstractExpression (org.voltdb.expressions.AbstractExpression)16 ArrayList (java.util.ArrayList)6 ComparisonExpression (org.voltdb.expressions.ComparisonExpression)6 JSONException (org.json_voltpatches.JSONException)5 VoltType (org.voltdb.VoltType)5 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)5 Constraint (org.voltdb.catalog.Constraint)4 VoltXMLElement (org.hsqldb_voltpatches.VoltXMLElement)3 Column (org.voltdb.catalog.Column)3 AggregateExpression (org.voltdb.expressions.AggregateExpression)3 ColumnRef (org.voltdb.catalog.ColumnRef)2 MaterializedViewHandlerInfo (org.voltdb.catalog.MaterializedViewHandlerInfo)2 MaterializedViewInfo (org.voltdb.catalog.MaterializedViewInfo)2 OperatorExpression (org.voltdb.expressions.OperatorExpression)2 SelectSubqueryExpression (org.voltdb.expressions.SelectSubqueryExpression)2 WindowFunctionExpression (org.voltdb.expressions.WindowFunctionExpression)2 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)2 AggregatePlanNode (org.voltdb.plannodes.AggregatePlanNode)2 HashAggregatePlanNode (org.voltdb.plannodes.HashAggregatePlanNode)2