/** * @param paramsById * @param exprNode * @return */ private static AbstractExpression parseOperationExpression( HashMap<Long, Integer> paramsById, 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); // 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 = parseExpressionTree(paramsById, 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 = parseExpressionTree(paramsById, 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). expr.setValueSize(voltType.getMaxLengthInBytes()); } } return expr; }
/** * @param paramsById * @param exprNode * @return */ private static AbstractExpression parseAggregationExpression( HashMap<Long, Integer> paramsById, VoltXMLElement exprNode) { String type = exprNode.attributes.get("optype"); ExpressionType exprType = ExpressionType.get(type); if (exprType == ExpressionType.INVALID) { throw new PlanningErrorException("Unsupported aggregation type '" + type + "'"); } // Allow expressions to read expression-specific data from exprNode. // The design fully abstracts other volt classes from the XML serialization. // So, this goes here instead of in derived Expression implementations. 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 = parseExpressionTree(paramsById, 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(); } return expr; }