use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class AbstractParsedStmt method parseParameters.
/**
* Populate the statement's paramList from the "parameters" element. Each
* parameter has an id and an index, both of which are numeric. It also has
* a type and an indication of whether it's a vector parameter. For each
* parameter, we create a ParameterValueExpression, named pve, which holds
* the type and vector parameter indication. We add the pve to two maps,
* m_paramsById and m_paramsByIndex.
*
* We also set a counter, MAX_PARAMETER_ID, to the largest id in the
* expression. This helps give ids to references to correlated expressions
* of subqueries.
*
* @param paramsNode
*/
protected void parseParameters(VoltXMLElement root) {
VoltXMLElement paramsNode = null;
for (VoltXMLElement node : root.children) {
if (node.name.equalsIgnoreCase("parameters")) {
paramsNode = node;
break;
}
}
if (paramsNode == null) {
return;
}
long max_parameter_id = -1;
for (VoltXMLElement node : paramsNode.children) {
if (node.name.equalsIgnoreCase("parameter")) {
long id = Long.parseLong(node.attributes.get("id"));
int index = Integer.parseInt(node.attributes.get("index"));
if (index > max_parameter_id) {
max_parameter_id = index;
}
String typeName = node.attributes.get("valuetype");
String isVectorParam = node.attributes.get("isvector");
VoltType type = VoltType.typeFromString(typeName);
ParameterValueExpression pve = new ParameterValueExpression();
pve.setParameterIndex(index);
pve.setValueType(type);
if (isVectorParam != null && isVectorParam.equalsIgnoreCase("true")) {
pve.setParamIsVector();
}
m_paramsById.put(id, pve);
m_paramsByIndex.put(index, pve);
}
}
if (max_parameter_id >= NEXT_PARAMETER_ID) {
NEXT_PARAMETER_ID = (int) max_parameter_id + 1;
}
}
use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class AbstractParsedStmt method parseValueExpression.
/**
*
* @param paramsById
* @param exprNode
* @return
*/
private AbstractExpression parseValueExpression(VoltXMLElement exprNode) {
String isParam = exprNode.attributes.get("isparam");
String isPlannerGenerated = exprNode.attributes.get("isplannergenerated");
// A ParameterValueExpression is needed to represent any user-provided or planner-injected parameter.
boolean needParameter = (isParam != null) && (isParam.equalsIgnoreCase("true"));
// A ConstantValueExpression is needed to represent a constant in the statement,
// EVEN if that constant has been "parameterized" by the plan caching code.
ConstantValueExpression cve = null;
boolean needConstant = (needParameter == false) || ((isPlannerGenerated != null) && (isPlannerGenerated.equalsIgnoreCase("true")));
if (needConstant) {
String type = exprNode.attributes.get("valuetype");
VoltType vt = VoltType.typeFromString(type);
assert (vt != VoltType.VOLTTABLE);
cve = new ConstantValueExpression();
cve.setValueType(vt);
if ((vt != VoltType.NULL) && (vt != VoltType.NUMERIC)) {
int size = vt.getMaxLengthInBytes();
cve.setValueSize(size);
}
if (!needParameter && vt != VoltType.NULL) {
String valueStr = exprNode.attributes.get("value");
// given type.
if (valueStr != null) {
try {
switch(vt) {
case BIGINT:
case TIMESTAMP:
Long.valueOf(valueStr);
break;
case FLOAT:
Double.valueOf(valueStr);
break;
case DECIMAL:
VoltDecimalHelper.stringToDecimal(valueStr);
break;
default:
break;
}
} catch (PlanningErrorException ex) {
// We're happy with these.
throw ex;
} catch (NumberFormatException ex) {
throw new PlanningErrorException("Numeric conversion error to type " + vt.name() + " " + ex.getMessage().toLowerCase());
} catch (Exception ex) {
throw new PlanningErrorException(ex.getMessage());
}
}
cve.setValue(valueStr);
}
}
if (needParameter) {
long id = Long.parseLong(exprNode.attributes.get("id"));
ParameterValueExpression expr = m_paramsById.get(id);
assert (expr != null);
if (needConstant) {
expr.setOriginalValue(cve);
cve.setValue(m_paramValues[expr.getParameterIndex()]);
}
return expr;
}
return cve;
}
use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class AbstractParsedStmt method replaceExpressionsWithPve.
/**
* Helper method to replace all TVEs and aggregated expressions with the corresponding PVEs.
* The original expressions are placed into the map to be propagated to the EE.
* The key to the map is the parameter index.
*
*
* @param stmt - subquery statement
* @param expr - expression with parent TVEs
* @return Expression with parent TVE replaced with PVE
*/
protected AbstractExpression replaceExpressionsWithPve(AbstractExpression expr) {
assert (expr != null);
if (expr instanceof TupleValueExpression) {
int paramIdx = NEXT_PARAMETER_ID++;
ParameterValueExpression pve = new ParameterValueExpression(paramIdx, expr);
m_parameterTveMap.put(paramIdx, expr);
return pve;
}
if (expr instanceof AggregateExpression) {
int paramIdx = NEXT_PARAMETER_ID++;
ParameterValueExpression pve = new ParameterValueExpression(paramIdx, expr);
// Disallow aggregation of parent columns in a subquery.
// except the case HAVING AGG(T1.C1) IN (SELECT T2.C2 ...)
List<TupleValueExpression> tves = ExpressionUtil.getTupleValueExpressions(expr);
assert (m_parentStmt != null);
for (TupleValueExpression tve : tves) {
int origId = tve.getOrigStmtId();
if (m_stmtId != origId && m_parentStmt.m_stmtId != origId) {
throw new PlanningErrorException("Subqueries do not support aggregation of parent statement columns");
}
}
m_parameterTveMap.put(paramIdx, expr);
return pve;
}
if (expr.getLeft() != null) {
expr.setLeft(replaceExpressionsWithPve(expr.getLeft()));
}
if (expr.getRight() != null) {
expr.setRight(replaceExpressionsWithPve(expr.getRight()));
}
if (expr.getArgs() != null) {
List<AbstractExpression> newArgs = new ArrayList<>();
for (AbstractExpression argument : expr.getArgs()) {
newArgs.add(replaceExpressionsWithPve(argument));
}
expr.setArgs(newArgs);
}
return expr;
}
use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class AbstractParsedStmt method parseColumnRefExpression.
/**
*
* @param exprNode
* @return
*/
private AbstractExpression parseColumnRefExpression(VoltXMLElement exprNode) {
String tableName = exprNode.attributes.get("table");
if (tableName == null) {
assert (m_DDLIndexedTable != null);
tableName = m_DDLIndexedTable.getTypeName();
}
assert (tableName != null);
String tableAlias = exprNode.attributes.get("tablealias");
if (tableAlias == null) {
tableAlias = tableName;
}
String columnName = exprNode.attributes.get("column");
String columnAlias = exprNode.attributes.get("alias");
// Whether or not this column is the coalesced column produced by a join with a
// USING predicate.
String usingAttr = exprNode.attributes.get("using");
boolean isUsingColumn = usingAttr != null ? Boolean.parseBoolean(usingAttr) : false;
// Use the index produced by HSQL as a way to differentiate columns that have
// the same name with a single table (which can happen for subqueries containing joins).
int differentiator = Integer.parseInt(exprNode.attributes.get("index"));
if (differentiator == -1 && isUsingColumn) {
for (VoltXMLElement usingElem : exprNode.children) {
String usingTableAlias = usingElem.attributes.get("tablealias");
if (usingTableAlias != null && usingTableAlias.equals(tableAlias)) {
differentiator = Integer.parseInt(usingElem.attributes.get("index"));
}
}
}
TupleValueExpression tve = new TupleValueExpression(tableName, tableAlias, columnName, columnAlias, -1, differentiator);
// Collect the unique columns used in the plan for a given scan.
// Resolve the tve and add it to the scan's cache of referenced columns
// Get tableScan where this TVE is originated from. In case of the
// correlated queries it may not be THIS statement but its parent
StmtTableScan tableScan = resolveStmtTableScanByAlias(tableAlias);
if (tableScan == null) {
// from TestVoltCompler.testScalarSubqueriesExpectedFailures.
throw new PlanningErrorException("Object not found: " + tableAlias);
}
AbstractExpression resolvedExpr = tableScan.resolveTVE(tve);
if (m_stmtId == tableScan.getStatementId()) {
return resolvedExpr;
}
// This is a TVE from the correlated expression
int paramIdx = NEXT_PARAMETER_ID++;
ParameterValueExpression pve = new ParameterValueExpression(paramIdx, resolvedExpr);
m_parameterTveMap.put(paramIdx, resolvedExpr);
return pve;
}
use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class AbstractParsedStmt method parameterCountIndexById.
/// This is for use with integer-valued row count parameters, namely LIMITs and OFFSETs.
/// It should be called (at least) once for each LIMIT or OFFSET parameter to establish that
/// the parameter is being used in a BIGINT context.
/// There may be limitations elsewhere that restrict limits and offsets to 31-bit unsigned values,
/// but enforcing that at parameter passing/checking time seems a little arbitrary, so we keep
/// the parameters at maximum width -- a 63-bit unsigned BIGINT.
protected int parameterCountIndexById(long paramId) {
if (paramId == -1) {
return -1;
}
assert (m_paramsById.containsKey(paramId));
ParameterValueExpression pve = m_paramsById.get(paramId);
// As a side effect, re-establish these parameters as integer-typed
// -- this helps to catch type errors earlier in the invocation process
// and prevents a more serious error in HSQLBackend statement reconstruction.
// The HSQL parser originally had these correctly pegged as BIGINTs,
// but the VoltDB code ( @see AbstractParsedStmt#parseParameters )
// skeptically second-guesses that pending its own verification. This case is now verified.
pve.refineValueType(VoltType.BIGINT, VoltType.BIGINT.getLengthInBytesForFixedTypes());
return pve.getParameterIndex();
}
Aggregations