use of org.hsqldb_voltpatches.VoltXMLElement in project voltdb by VoltDB.
the class ParsedInsertStmt method parse.
@Override
void parse(VoltXMLElement stmtNode) {
// but those table scans will belong to the corresponding ParsedSelectStmt
assert (m_tableList.isEmpty());
String tableName = stmtNode.attributes.get("table");
// Need to add the table to the cache. It may be required to resolve the
// correlated TVE in case of WHERE clause contains IN subquery
Table table = getTableFromDB(tableName);
addTableToStmtCache(table, tableName);
m_tableList.add(table);
for (VoltXMLElement node : stmtNode.children) {
if (node.name.equals("columns")) {
parseTargetColumns(node, table, m_columns);
} else if (node.name.equals(SELECT_NODE_NAME)) {
m_subquery = new StmtSubqueryScan(parseSubquery(node), "__VOLT_INSERT_SUBQUERY__");
// Until scalar subqueries are allowed in INSERT ... VALUES statements,
// The top-level SELECT subquery in an INSERT ... SELECT statement
// is the only possible subselect in an INSERT statement.
m_scans.add(m_subquery);
} else if (node.name.equals(UNION_NODE_NAME)) {
throw new PlanningErrorException("INSERT INTO ... SELECT is not supported for UNION or other set operations.");
}
}
calculateContentDeterminismMessage();
}
use of org.hsqldb_voltpatches.VoltXMLElement in project voltdb by VoltDB.
the class AbstractParsedStmt method parseTable.
/**
*
* @param tableNode
*/
private void parseTable(VoltXMLElement tableNode) {
String tableName = tableNode.attributes.get("table");
assert (tableName != null);
String tableAlias = tableNode.attributes.get("tablealias");
if (tableAlias == null) {
tableAlias = tableName;
}
// Hsql rejects name conflicts in a single query
m_tableAliasListAsJoinOrder.add(tableAlias);
VoltXMLElement subqueryElement = null;
// Possible sub-query
for (VoltXMLElement childNode : tableNode.children) {
if (!childNode.name.equals("tablesubquery")) {
continue;
}
if (childNode.children.isEmpty()) {
continue;
}
// sub-query FROM (SELECT ...)
subqueryElement = childNode.children.get(0);
break;
}
// add table to the query cache before processing the JOIN/WHERE expressions
// The order is important because processing sub-query expressions assumes that
// the sub-query is already registered
StmtTableScan tableScan = null;
Table table = null;
// In case of a subquery we need to preserve its filter expressions
AbstractExpression simplifiedSubqueryFilter = null;
if (subqueryElement == null) {
table = getTableFromDB(tableName);
assert (table != null);
tableScan = addTableToStmtCache(table, tableAlias);
m_tableList.add(table);
} else {
AbstractParsedStmt subquery = parseFromSubQuery(subqueryElement);
StmtSubqueryScan subqueryScan = addSubqueryToStmtCache(subquery, tableAlias);
tableScan = subqueryScan;
StmtTargetTableScan simpler = simplifierForSubquery(subquery);
if (simpler != null) {
tableScan = addSimplifiedSubqueryToStmtCache(subqueryScan, simpler);
table = simpler.getTargetTable();
// Extract subquery's filters
assert (subquery.m_joinTree != null);
// Adjust the table alias in all TVEs from the eliminated
// subquery expressions. Example:
// SELECT TA2.CA FROM (SELECT C CA FROM T TA1 WHERE C > 0) TA2
// The table alias TA1 from the original TVE (T)TA1.C from the
// subquery WHERE condition needs to be replaced with the alias
// TA2. The new TVE will be (T)TA2.C.
// The column alias does not require an adjustment.
simplifiedSubqueryFilter = subquery.m_joinTree.getAllFilters();
List<TupleValueExpression> tves = ExpressionUtil.getTupleValueExpressions(simplifiedSubqueryFilter);
for (TupleValueExpression tve : tves) {
tve.setTableAlias(tableScan.getTableAlias());
tve.setOrigStmtId(m_stmtId);
}
}
}
AbstractExpression joinExpr = parseJoinCondition(tableNode);
AbstractExpression whereExpr = parseWhereCondition(tableNode);
if (simplifiedSubqueryFilter != null) {
// Add subqueruy's expressions as JOIN filters to make sure they will
// stay at the node level in case of an OUTER joins and won't affect
// the join simplification process:
// select * from T LEFT JOIN (select C FROM T1 WHERE C > 2) S ON T.C = S.C;
joinExpr = (joinExpr != null) ? ExpressionUtil.combine(joinExpr, simplifiedSubqueryFilter) : simplifiedSubqueryFilter;
}
// The join type of the leaf node is always INNER
// For a new tree its node's ids start with 0 and keep incrementing by 1
int nodeId = (m_joinTree == null) ? 0 : m_joinTree.getId() + 1;
JoinNode leafNode;
if (table != null) {
assert (tableScan instanceof StmtTargetTableScan);
leafNode = new TableLeafNode(nodeId, joinExpr, whereExpr, (StmtTargetTableScan) tableScan);
} else {
assert (tableScan instanceof StmtSubqueryScan);
leafNode = new SubqueryLeafNode(nodeId, joinExpr, whereExpr, (StmtSubqueryScan) tableScan);
leafNode.updateContentDeterminismMessage(((StmtSubqueryScan) tableScan).calculateContentDeterminismMessage());
}
if (m_joinTree == null) {
// this is the first table
m_joinTree = leafNode;
} else {
// Build the tree by attaching the next table always to the right
// The node's join type is determined by the type of its right node
JoinType joinType = JoinType.get(tableNode.attributes.get("jointype"));
assert (joinType != JoinType.INVALID);
JoinNode joinNode = new BranchNode(nodeId + 1, joinType, m_joinTree, leafNode);
m_joinTree = joinNode;
}
}
use of org.hsqldb_voltpatches.VoltXMLElement 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;
}
use of org.hsqldb_voltpatches.VoltXMLElement in project voltdb by VoltDB.
the class ParameterizationInfo method findUserParametersRecursively.
public static void findUserParametersRecursively(final VoltXMLElement xmlSQL, Set<Integer> paramIds) {
if (xmlSQL.name.equals("union")) {
// UNION has its parameters on the individual selects level
for (VoltXMLElement xmlChildSQL : xmlSQL.children) {
findUserParametersRecursively(xmlChildSQL, paramIds);
}
} else {
// find the parameters xml node
for (VoltXMLElement child : xmlSQL.children) {
if (!child.name.equals("parameters")) {
continue;
}
// also including its subqueries if it has.
for (VoltXMLElement node : child.children) {
String idStr = node.attributes.get("id");
assert (idStr != null);
// ID attribute is assumed to be global unique per query.
// but for UNION query, "paramerters" are copied to each query level.
paramIds.add(Integer.parseInt(idStr));
}
// there is ONLY one parameters element per query
break;
}
}
}
use of org.hsqldb_voltpatches.VoltXMLElement in project voltdb by VoltDB.
the class ParameterizationInfo method parameterizeRecursively.
static void parameterizeRecursively(VoltXMLElement node, VoltXMLElement paramsNode, Map<String, Integer> idToParamIndexMap, List<String> paramValues) {
if (node.name.equals("value")) {
String idStr = node.attributes.get("id");
assert (idStr != null);
// A value id is currently a "string-formatted long", but there's no need to commit
// to that format in this early processing -- here, the id just needs to be a unique
// string for each parsed value. It allows hsql to replicate a parameter reference
// within its parse trees without causing code like this to lose track of its identity.
Integer paramIndex = idToParamIndexMap.get(idStr);
if (paramIndex == null) {
// Use the next param index for each new value with an unfamiliar id,
// starting at 0.
paramIndex = paramValues.size();
// Later references to this value's id will re-use this same param index.
idToParamIndexMap.put(idStr, paramIndex);
VoltXMLElement paramIndexNode = new VoltXMLElement("parameter");
paramIndexNode.attributes.put("index", String.valueOf(paramIndex));
paramIndexNode.attributes.put("id", idStr);
paramsNode.children.add(paramIndexNode);
// handle parameter value type
String typeStr = node.attributes.get("valuetype");
VoltType vt = VoltType.typeFromString(typeStr);
String value = null;
if (vt != VoltType.NULL) {
value = node.attributes.get("value");
}
paramValues.add(value);
// Thanks for Hsqldb 1.9, FLOAT literal values have been handled well with E sign.
if (vt == VoltType.NUMERIC) {
vt = VoltTypeUtil.getNumericLiteralType(VoltType.BIGINT, value);
}
node.attributes.put("valuetype", vt.getName());
paramIndexNode.attributes.put("valuetype", vt.getName());
}
// Assume that all values, whether or not their ids have been seen before, can
// be considered planner-generated parameters (proxies for user-provided constants).
// This is one simplification that leverages the fact that statements that came with
// user-provided parameters were barred from being (further) parameterized.
node.attributes.put("isparam", "true");
node.attributes.put("isplannergenerated", "true");
// Remove the "value" attribute -- this is the critical step to folding
// different raw VoltXML trees into the same parameterized VoltXML tree.
// The value differences are extracted into paramValues for future reference by:
// the execution engine which needs to substitute actual values for all parameters
// to run the query
// the index scan planner which may need to "bind" the parameters to their original
// values to apply indexes on expressions like "(colA + 2 * colB)" when used in a query
// like "... WHERE t2.colA + 2 * t2.colB > 3*t1.colC".
node.attributes.remove("value");
}
for (VoltXMLElement child : node.children) {
parameterizeRecursively(child, paramsNode, idToParamIndexMap, paramValues);
}
}
Aggregations