use of org.hsqldb_voltpatches.VoltXMLElement in project voltdb by VoltDB.
the class ParsedColInfo method fromOrderByXml.
/** Construct a ParsedColInfo from Volt XML.
* Allow caller to specify actions to finalize the parsed expression.
*/
public static ParsedColInfo fromOrderByXml(AbstractParsedStmt parsedStmt, VoltXMLElement orderByXml, ExpressionAdjuster adjuster) {
// make sure everything is kosher
assert (orderByXml.name.equalsIgnoreCase("orderby"));
// get desc/asc
String desc = orderByXml.attributes.get("desc");
boolean descending = (desc != null) && (desc.equalsIgnoreCase("true"));
// get the columnref or other expression inside the orderby node
VoltXMLElement child = orderByXml.children.get(0);
assert (child != null);
// create the orderby column
ParsedColInfo orderCol = new ParsedColInfo();
orderCol.orderBy = true;
orderCol.ascending = !descending;
AbstractExpression orderExpr = parsedStmt.parseExpressionTree(child);
assert (orderExpr != null);
orderCol.expression = adjuster.adjust(orderExpr);
// right thing later.
if (orderExpr instanceof TupleValueExpression) {
TupleValueExpression tve = (TupleValueExpression) orderExpr;
orderCol.columnName = tve.getColumnName();
orderCol.tableName = tve.getTableName();
orderCol.tableAlias = tve.getTableAlias();
if (orderCol.tableAlias == null) {
orderCol.tableAlias = orderCol.tableName;
}
orderCol.alias = tve.getColumnAlias();
} else {
String alias = child.attributes.get("alias");
orderCol.alias = alias;
orderCol.tableName = AbstractParsedStmt.TEMP_TABLE_NAME;
orderCol.tableAlias = AbstractParsedStmt.TEMP_TABLE_NAME;
orderCol.columnName = "";
if ((child.name.equals("operation") == false) && (child.name.equals("aggregation") == false) && (child.name.equals("win_aggregation") == false) && (child.name.equals("function") == false) && (child.name.equals("rank") == false) && (child.name.equals("value") == false) && (child.name.equals("columnref") == false)) {
throw new RuntimeException("ORDER BY parsed with strange child node type: " + child.name);
}
}
return orderCol;
}
use of org.hsqldb_voltpatches.VoltXMLElement in project voltdb by VoltDB.
the class AbstractParsedStmt method parseTargetColumns.
void parseTargetColumns(VoltXMLElement columnsNode, Table table, HashMap<Column, AbstractExpression> columns) {
for (VoltXMLElement child : columnsNode.children) {
assert (child.name.equals("column"));
String name = child.attributes.get("name");
assert (name != null);
Column col = table.getColumns().getExact(name.trim());
// May be no children of column node in the case of
// INSERT INTO ... SELECT ...
AbstractExpression expr = null;
if (child.children.size() != 0) {
assert (child.children.size() == 1);
VoltXMLElement subChild = child.children.get(0);
expr = parseExpressionTree(subChild);
assert (expr != null);
expr.refineValueType(VoltType.get((byte) col.getType()), col.getSize());
ExpressionUtil.finalizeValueTypes(expr);
}
columns.put(col, expr);
}
}
use of org.hsqldb_voltpatches.VoltXMLElement 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;
}
use of org.hsqldb_voltpatches.VoltXMLElement in project voltdb by VoltDB.
the class IndexAVL method voltGetIndexXML.
/**
* VoltDB added method to get a non-catalog-dependent
* representation of this HSQLDB object.
* @param session The current Session object may be needed to resolve
* some names.
* @return XML, correctly indented, representing this object.
* @throws HSQLParseException
*/
@Override
public VoltXMLElement voltGetIndexXML(Session session, String tableName, Map<String, VoltXMLElement> indexConstraintMapping) throws org.hsqldb_voltpatches.HSQLInterface.HSQLParseException {
org.hsqldb_voltpatches.VoltXMLElement index = new org.hsqldb_voltpatches.VoltXMLElement("index");
// Add any expressions to the XML representation of the index,
// and compute a hash that will help uniquify the generated name,
// if a name was not provided.
int exprHash = 0;
if (exprs != null) {
org.hsqldb_voltpatches.VoltXMLElement indexedExprs = new org.hsqldb_voltpatches.VoltXMLElement("exprs");
index.children.add(indexedExprs);
String hashExprString = new String();
String sep = "";
for (org.hsqldb_voltpatches.Expression expression : exprs) {
org.hsqldb_voltpatches.VoltXMLElement xml = expression.voltGetExpressionXML(session, (Table) table);
indexedExprs.children.add(xml);
hashExprString += sep + expression.getSQL();
sep = ",";
}
byte[] bytes = hashExprString.getBytes();
for (int ii = 0; ii < bytes.length; ii++) {
exprHash = 31 * exprHash + bytes[ii];
}
}
String hsqlIndexName = getName().name;
String voltdbIndexName = null;
boolean isHashIndex = false;
if (indexConstraintMapping.containsKey(hsqlIndexName)) {
// This is an index backing a constraint.
VoltXMLElement constraintXml = indexConstraintMapping.get(hsqlIndexName);
indexConstraintMapping.remove(hsqlIndexName);
boolean isAutoName = constraintXml.attributes.get("nameisauto").equals("true");
// This is either a [ASSUME]UNIQUE constraint or a PK.
String constraintType = constraintXml.attributes.get("constrainttype");
String hsqlConstraintName = constraintXml.attributes.get("name");
if (!isAutoName) {
isHashIndex = isNameRequestingHashIndex(hsqlConstraintName);
voltdbIndexName = HSQLInterface.AUTO_GEN_NAMED_CONSTRAINT_IDX + hsqlConstraintName;
} else {
String prefix = null;
boolean isPrimaryKey = constraintType.equals("PRIMARY_KEY");
if (isPrimaryKey) {
prefix = HSQLInterface.AUTO_GEN_PRIMARY_KEY_PREFIX;
} else {
prefix = HSQLInterface.AUTO_GEN_UNIQUE_IDX_PREFIX;
}
String namePart = tableName + "_" + StringUtils.join(getColumnNameList().toArray(), "_");
if (exprs != null) {
namePart += "_" + java.lang.Math.abs(exprHash % 100000);
}
voltdbIndexName = prefix + namePart;
// Also name the constraint here based on our naming scheme.
String voltdbConstraintName = null;
if (isPrimaryKey) {
voltdbConstraintName = HSQLInterface.AUTO_GEN_CONSTRAINT_PREFIX + "_PK_" + namePart;
} else {
voltdbConstraintName = HSQLInterface.AUTO_GEN_CONSTRAINT_PREFIX + "_CT_" + namePart;
}
constraintXml.attributes.put("name", voltdbConstraintName);
}
// Update the index name in the constraint.
constraintXml.attributes.put("index", voltdbIndexName);
} else {
// This is an index created via CREATE INDEX
isHashIndex = isNameRequestingHashIndex(hsqlIndexName);
voltdbIndexName = hsqlIndexName;
}
index.attributes.put("name", voltdbIndexName);
index.attributes.put("ishashindex", isHashIndex ? "true" : "false");
index.attributes.put("assumeunique", isAssumeUnique() ? "true" : "false");
index.attributes.put("unique", isUnique() ? "true" : "false");
Object[] columnList = getColumnNameList().toArray();
index.attributes.put("columns", StringUtils.join(columnList, ","));
if (predicate != null) {
org.hsqldb_voltpatches.VoltXMLElement partialExpr = new org.hsqldb_voltpatches.VoltXMLElement("predicate");
index.children.add(partialExpr);
org.hsqldb_voltpatches.VoltXMLElement xml = predicate.voltGetExpressionXML(session, (Table) table);
partialExpr.children.add(xml);
}
return index;
}
use of org.hsqldb_voltpatches.VoltXMLElement in project voltdb by VoltDB.
the class ParsedSelectStmt method parse.
@Override
void parse(VoltXMLElement stmtNode) {
String node;
if ((node = stmtNode.attributes.get("distinct")) != null) {
m_distinct = Boolean.parseBoolean(node);
}
VoltXMLElement limitElement = null;
VoltXMLElement offsetElement = null;
VoltXMLElement havingElement = null;
VoltXMLElement displayElement = null;
VoltXMLElement orderbyElement = null;
VoltXMLElement groupbyElement = null;
for (VoltXMLElement child : stmtNode.children) {
if (child.name.equalsIgnoreCase("limit")) {
assert (limitElement == null);
limitElement = child;
} else if (child.name.equalsIgnoreCase("offset")) {
assert (offsetElement == null);
offsetElement = child;
} else if (child.name.equalsIgnoreCase("columns")) {
assert (displayElement == null);
displayElement = child;
} else if (child.name.equalsIgnoreCase("ordercolumns")) {
assert (orderbyElement == null);
orderbyElement = child;
} else if (child.name.equalsIgnoreCase("groupcolumns")) {
assert (groupbyElement == null);
groupbyElement = child;
} else if (child.name.equalsIgnoreCase("having")) {
assert (havingElement == null);
havingElement = child;
}
}
parseLimitAndOffset(limitElement, offsetElement, m_limitOffset);
if (m_aggregationList == null) {
m_aggregationList = new ArrayList<>();
}
// finding TVEs for pass-through columns.
assert (displayElement != null);
parseDisplayColumns(displayElement, false);
// rewrite DISTINCT
// function may need to change the groupbyElement by rewriting.
groupbyElement = processDistinct(displayElement, groupbyElement, havingElement);
if (groupbyElement != null) {
parseGroupByColumns(groupbyElement);
insertToColumnList(m_aggResultColumns, m_groupByColumns);
}
if (havingElement != null) {
parseHavingExpression(havingElement, false);
}
if (orderbyElement != null && !hasAOneRowResult()) {
parseOrderColumns(orderbyElement, false);
}
// At this point, we have collected all aggregations in the select
// statement. We do not need aggregationList container in parseXMLtree
// Make it null to prevent others adding elements to it when parsing
// the tree.
m_aggregationList = null;
if (needComplexAggregation()) {
fillUpAggResultColumns();
} else {
m_aggResultColumns = m_displayColumns;
}
// If we have seen any windowed expressions we will have
// saved them in m_windowFunctionExpressions by now. We need to
// verify their validity.
verifyWindowFunctionExpressions();
/*
* Calculate the content determinism message before we place the TVEs in
* the columns. After the TVEs are placed the actual expressions are
* hard to find.
*/
calculateContentDeterminismMessage();
placeTVEsinColumns();
// prepare the limit plan node if it needs one.
if (hasLimitOrOffset()) {
m_limitOffset.m_limitCanPushdown = canPushdownLimit();
prepareLimitPlanNode(this, m_limitOffset);
}
// Prepare for the AVG push-down optimization only if it might be required.
if (mayNeedAvgPushdown()) {
processAvgPushdownOptimization(displayElement, groupbyElement, havingElement, orderbyElement);
}
prepareMVBasedQueryFix();
}
Aggregations