use of org.hsqldb_voltpatches.HSQLInterface.HSQLParseException in project voltdb by VoltDB.
the class PlannerTool method planSql.
public synchronized AdHocPlannedStatement planSql(String sqlIn, StatementPartitioning partitioning, boolean isExplainMode, final Object[] userParams, boolean isSwapTables) {
CacheUse cacheUse = CacheUse.FAIL;
if (m_plannerStats != null) {
m_plannerStats.startStatsCollection();
}
boolean hasUserQuestionMark = false;
boolean wrongNumberParameters = false;
try {
if ((sqlIn == null) || (sqlIn.length() == 0)) {
throw new RuntimeException("Can't plan empty or null SQL.");
}
// remove any spaces or newlines
String sql = sqlIn.trim();
// if the cases tended to have mostly overlapping queries.
if (partitioning.isInferred()) {
// Check the literal cache for a match.
AdHocPlannedStatement cachedPlan = m_cache.getWithSQL(sqlIn);
if (cachedPlan != null) {
cacheUse = CacheUse.HIT1;
return cachedPlan;
} else {
cacheUse = CacheUse.MISS;
}
}
// Reset plan node id counter
AbstractPlanNode.resetPlanNodeIds();
//////////////////////
// PLAN THE STMT
//////////////////////
TrivialCostModel costModel = new TrivialCostModel();
DatabaseEstimates estimates = new DatabaseEstimates();
QueryPlanner planner = new QueryPlanner(sql, "PlannerTool", "PlannerToolProc", m_database, partitioning, m_hsql, estimates, !VoltCompiler.DEBUG_MODE, AD_HOC_JOINED_TABLE_LIMIT, costModel, null, null, DeterminismMode.FASTER);
CompiledPlan plan = null;
String[] extractedLiterals = null;
String parsedToken = null;
try {
if (isSwapTables) {
planner.planSwapTables();
} else {
planner.parse();
}
parsedToken = planner.parameterize();
// check the parameters count
// check user input question marks with input parameters
int inputParamsLengh = userParams == null ? 0 : userParams.length;
if (planner.getAdhocUserParamsCount() != inputParamsLengh) {
wrongNumberParameters = true;
if (!isExplainMode) {
throw new PlanningErrorException(String.format("Incorrect number of parameters passed: expected %d, passed %d", planner.getAdhocUserParamsCount(), inputParamsLengh));
}
}
hasUserQuestionMark = planner.getAdhocUserParamsCount() > 0;
// do not put wrong parameter explain query into cache
if (!wrongNumberParameters && partitioning.isInferred()) {
// QueryPlanner.
assert (parsedToken != null);
extractedLiterals = planner.extractedParamLiteralValues();
List<BoundPlan> boundVariants = m_cache.getWithParsedToken(parsedToken);
if (boundVariants != null) {
assert (!boundVariants.isEmpty());
BoundPlan matched = null;
for (BoundPlan boundPlan : boundVariants) {
if (boundPlan.allowsParams(extractedLiterals)) {
matched = boundPlan;
break;
}
}
if (matched != null) {
CorePlan core = matched.m_core;
ParameterSet params = null;
if (planner.compiledAsParameterizedPlan()) {
params = planner.extractedParamValues(core.parameterTypes);
} else if (hasUserQuestionMark) {
params = ParameterSet.fromArrayNoCopy(userParams);
} else {
// No constants AdHoc queries
params = ParameterSet.emptyParameterSet();
}
AdHocPlannedStatement ahps = new AdHocPlannedStatement(sql.getBytes(Constants.UTF8ENCODING), core, params, null);
ahps.setBoundConstants(matched.m_constants);
// parameterized plan from the cache does not have exception
m_cache.put(sql, parsedToken, ahps, extractedLiterals, hasUserQuestionMark, false);
cacheUse = CacheUse.HIT2;
return ahps;
}
}
}
// If not caching or there was no cache hit, do the expensive full planning.
plan = planner.plan();
assert (plan != null);
if (plan != null && plan.getStatementPartitioning() != null) {
partitioning = plan.getStatementPartitioning();
}
} catch (Exception e) {
/*
* Don't log PlanningErrorExceptions or HSQLParseExceptions, as
* they are at least somewhat expected.
*/
String loggedMsg = "";
if (!((e instanceof PlanningErrorException) || (e instanceof HSQLParseException))) {
logException(e, "Error compiling query");
loggedMsg = " (Stack trace has been written to the log.)";
}
throw new RuntimeException("Error compiling query: " + e.toString() + loggedMsg, e);
}
if (plan == null) {
throw new RuntimeException("Null plan received in PlannerTool.planSql");
}
//////////////////////
// OUTPUT THE RESULT
//////////////////////
CorePlan core = new CorePlan(plan, m_catalogHash);
AdHocPlannedStatement ahps = new AdHocPlannedStatement(plan, core);
// do not put wrong parameter explain query into cache
if (!wrongNumberParameters && partitioning.isInferred()) {
// Note either the parameter index (per force to a user-provided parameter) or
// the actual constant value of the partitioning key inferred from the plan.
// Either or both of these two values may simply default
// to -1 and to null, respectively.
core.setPartitioningParamIndex(partitioning.getInferredParameterIndex());
core.setPartitioningParamValue(partitioning.getInferredPartitioningValue());
assert (parsedToken != null);
// Again, plans with inferred partitioning are the only ones supported in the cache.
m_cache.put(sqlIn, parsedToken, ahps, extractedLiterals, hasUserQuestionMark, planner.wasBadPameterized());
}
return ahps;
} finally {
if (m_plannerStats != null) {
m_plannerStats.endStatsCollection(m_cache.getLiteralCacheSize(), m_cache.getCoreCacheSize(), cacheUse, -1);
}
}
}
use of org.hsqldb_voltpatches.HSQLInterface.HSQLParseException in project voltdb by VoltDB.
the class Expression method voltGetXML.
/**
* VoltDB added method to get a non-catalog-dependent
* representation of this HSQLDB object.
* @param context The context encapsulates the current Session object and (optionally)
* select statement display columns that may be needed to resolve some names.
* @return A VoltXML tree structure.
* @throws HSQLParseException
*/
VoltXMLElement voltGetXML(SimpleColumnContext context, String realAlias) throws HSQLParseException {
// The voltXML representations of expressions tends to be driven much more by the expression's opType
// than its Expression class.
int exprOp = getType();
// That case gets explicitly enabled here by fudging the opType from SIMPLE_COLUMN to COLUMN.
if (exprOp == OpTypes.SIMPLE_COLUMN) {
VoltXMLElement asResolved = context.resolveSimpleColumn(this);
if (asResolved != null) {
return asResolved;
}
// ENG-10429 moved the following two lines here. See fix note https://issues.voltdb.com/browse/ENG-10429.
// convert the SIMPLE_COLUMN into a COLUMN
opType = OpTypes.COLUMN;
exprOp = OpTypes.COLUMN;
}
// Use the opType to find a pre-initialized prototype VoltXMLElement with the correct
// name and any required hard-coded values pre-set.
VoltXMLElement exp = prototypes.get(exprOp);
if (exp == null) {
// Must have found an unsupported opType.
throwForUnsupportedExpression(exprOp);
}
// Duplicate the prototype and add any expression particulars needed for the specific opType value,
// as well as a unique identifier, a possible alias, and child nodes.
exp = exp.duplicate();
exp.attributes.put("id", getUniqueId(context.m_session));
if (realAlias != null) {
exp.attributes.put("alias", realAlias);
} else if ((alias != null) && (getAlias().length() > 0)) {
exp.attributes.put("alias", getAlias());
}
// Add expression sub type
if (exprSubType == OpTypes.ANY_QUANTIFIED) {
exp.attributes.put("opsubtype", "any");
} else if (exprSubType == OpTypes.ALL_QUANTIFIED) {
exp.attributes.put("opsubtype", "all");
}
for (Expression expr : nodes) {
if (expr != null) {
VoltXMLElement vxmle = expr.voltGetXML(context, null);
exp.children.add(vxmle);
assert (vxmle != null);
}
}
// VoltXMLElement.
switch(exprOp) {
case OpTypes.VALUE:
// (I'm not sure why this MUST be the case --paul.)
if (valueData == null) {
String valueType = (dataType == null) ? "NULL" : Types.getTypeName(dataType.typeCode);
exp.attributes.put("valuetype", valueType);
return exp;
}
exp.attributes.put("valuetype", Types.getTypeName(dataType.typeCode));
if (valueData instanceof TimestampData) {
// When we get the default from the DDL,
// it gets jammed into a TimestampData object. If we
// don't do this, we get a Java class/reference
// string in the output schema for the DDL.
// EL HACKO: I'm just adding in the timezone seconds
// at the moment, hope this is right --izzy
TimestampData time = (TimestampData) valueData;
exp.attributes.put("value", Long.toString(Math.round((time.getSeconds() + time.getZone()) * 1e6) + time.getNanos() / 1000));
return exp;
}
// convert binary values to hex
if (valueData instanceof BinaryData) {
BinaryData bd = (BinaryData) valueData;
exp.attributes.put("value", hexEncode(bd.getBytes()));
return exp;
}
// Otherwise just string format the value.
if (dataType instanceof NumberType && !dataType.isIntegralType()) {
// remove the scentific exponent notation
exp.attributes.put("value", new BigDecimal(valueData.toString()).toPlainString());
return exp;
}
exp.attributes.put("value", valueData.toString());
return exp;
case OpTypes.COLUMN:
ExpressionColumn ec = (ExpressionColumn) this;
return ec.voltAnnotateColumnXML(exp);
case OpTypes.COALESCE:
return convertUsingColumnrefToCoaleseExpression(context.m_session, exp, dataType);
case OpTypes.SQL_FUNCTION:
FunctionSQL fn = (FunctionSQL) this;
return fn.voltAnnotateFunctionXML(exp);
case OpTypes.COUNT:
case OpTypes.SUM:
case OpTypes.AVG:
if (((ExpressionAggregate) this).isDistinctAggregate) {
exp.attributes.put("distinct", "true");
}
return exp;
case OpTypes.ORDER_BY:
if (((ExpressionOrderBy) this).isDescending()) {
exp.attributes.put("desc", "true");
}
return exp;
case OpTypes.CAST:
if (dataType == null) {
throw new HSQLParseException("VoltDB could not determine the type in a CAST operation");
}
exp.attributes.put("valuetype", dataType.getNameString());
return exp;
case OpTypes.TABLE_SUBQUERY:
if (subQuery == null || subQuery.queryExpression == null) {
throw new HSQLParseException("VoltDB could not determine the subquery");
}
ExpressionColumn[] parameters = new ExpressionColumn[0];
exp.children.add(StatementQuery.voltGetXMLExpression(subQuery.queryExpression, parameters, context.m_session));
return exp;
case OpTypes.ALTERNATIVE:
assert (nodes.length == 2);
// If with ELSE clause, pad NULL with it.
if (nodes[RIGHT] instanceof ExpressionValue) {
ExpressionValue val = (ExpressionValue) nodes[RIGHT];
if (val.valueData == null && val.dataType == Type.SQL_ALL_TYPES) {
exp.children.get(RIGHT).attributes.put("valuetype", dataType.getNameString());
}
}
case OpTypes.CASEWHEN:
// Hsql has check dataType can not be null.
assert (dataType != null);
exp.attributes.put("valuetype", dataType.getNameString());
return exp;
case OpTypes.WINDOWED_RANK:
case OpTypes.WINDOWED_DENSE_RANK:
case OpTypes.WINDOWED_COUNT:
case OpTypes.WINDOWED_MIN:
case OpTypes.WINDOWED_MAX:
case OpTypes.WINDOWED_SUM:
assert (dataType != null);
assert (this instanceof ExpressionWindowed);
exp.attributes.put("valuetype", dataType.getNameString());
ExpressionWindowed erank = (ExpressionWindowed) this;
return erank.voltAnnotateWindowedAggregateXML(exp, context);
default:
return exp;
}
}
use of org.hsqldb_voltpatches.HSQLInterface.HSQLParseException in project voltdb by VoltDB.
the class DDLCompiler method processVoltDBStatements.
private void processVoltDBStatements(final Database db, final DdlProceduresToLoad whichProcs, DDLStatement stmt) throws VoltCompilerException {
boolean processed = false;
try {
// Process a VoltDB-specific DDL statement, like PARTITION, REPLICATE,
// CREATE PROCEDURE, CREATE FUNCTION, and CREATE ROLE.
processed = m_voltStatementProcessor.process(stmt, db, whichProcs);
} catch (VoltCompilerException e) {
// Reformat the message thrown by VoltDB DDL processing to have a line number.
String msg = "VoltDB DDL Error: \"" + e.getMessage() + "\" in statement starting on lineno: " + stmt.lineNo;
throw m_compiler.new VoltCompilerException(msg);
}
if (!processed) {
try {
//* enable to debug */ System.out.println("DEBUG: " + stmt.statement);
// kind of ugly. We hex-encode each statement so we can
// avoid embedded newlines so we can delimit statements
// with newline.
m_fullDDL += Encoder.hexEncode(stmt.statement) + "\n";
// figure out what table this DDL might affect to minimize diff processing
HSQLDDLInfo ddlStmtInfo = HSQLLexer.preprocessHSQLDDL(stmt.statement);
// Get the diff that results from applying this statement and apply it
// to our local tree (with Volt-specific additions)
VoltXMLDiff thisStmtDiff = m_hsql.runDDLCommandAndDiff(ddlStmtInfo, stmt.statement);
// null diff means no change (usually drop if exists for non-existent thing)
if (thisStmtDiff != null) {
applyDiff(thisStmtDiff);
}
// special treatment for stream syntax
if (ddlStmtInfo.creatStream) {
processCreateStreamStatement(stmt, db, whichProcs);
}
} catch (HSQLParseException e) {
String msg = "DDL Error: \"" + e.getMessage() + "\" in statement starting on lineno: " + stmt.lineNo;
throw m_compiler.new VoltCompilerException(msg, stmt.lineNo);
}
}
}
use of org.hsqldb_voltpatches.HSQLInterface.HSQLParseException in project voltdb by VoltDB.
the class RangeVariable method voltGetRangeVariableXML.
/************************* Volt DB Extensions *************************/
/**
* 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
*/
VoltXMLElement voltGetRangeVariableXML(Session session) throws org.hsqldb_voltpatches.HSQLInterface.HSQLParseException {
Index index;
Index primaryIndex;
index = rangeIndex;
primaryIndex = rangeTable.getPrimaryIndex();
// note: ignored if scan if full table scan
if (index == null)
index = primaryIndex;
// output open tag
VoltXMLElement scan = new VoltXMLElement("tablescan");
if (rangeTable.tableType == TableBase.SYSTEM_SUBQUERY) {
if (rangeTable instanceof TableDerived) {
if (tableAlias == null || tableAlias.name == null) {
// VoltDB require derived sub select table with user specified alias
throw new org.hsqldb_voltpatches.HSQLInterface.HSQLParseException("SQL Syntax error: Every derived table must have its own alias.");
}
scan.attributes.put("table", tableAlias.name.toUpperCase());
VoltXMLElement subQuery = ((TableDerived) rangeTable).dataExpression.voltGetXML(session);
scan.children.add(subQuery);
}
} else {
scan.attributes.put("table", rangeTable.getName().name.toUpperCase());
}
if (tableAlias != null && !rangeTable.getName().name.equals(tableAlias)) {
scan.attributes.put("tablealias", tableAlias.name.toUpperCase());
}
// note if this is an outer join
if (isLeftJoin && isRightJoin) {
scan.attributes.put("jointype", "full");
} else if (isLeftJoin) {
scan.attributes.put("jointype", "left");
} else if (isRightJoin) {
scan.attributes.put("jointype", "right");
} else {
scan.attributes.put("jointype", "inner");
}
Expression joinCond = null;
Expression whereCond = null;
// else if indexCondition is set then it is where condition
if (isJoinIndex == true) {
joinCond = indexCondition;
if (indexEndCondition != null) {
joinCond = makeConjunction(joinCond, indexEndCondition);
}
// then go to the nonIndexJoinCondition
if (nonIndexJoinCondition != null) {
joinCond = makeConjunction(joinCond, nonIndexJoinCondition);
}
// then go to the nonIndexWhereCondition
whereCond = nonIndexWhereCondition;
} else {
joinCond = nonIndexJoinCondition;
whereCond = indexCondition;
if (indexEndCondition != null) {
whereCond = makeConjunction(whereCond, indexEndCondition);
}
// then go to the nonIndexWhereCondition
if (nonIndexWhereCondition != null) {
whereCond = makeConjunction(whereCond, nonIndexWhereCondition);
}
}
if (joinCond != null) {
joinCond = joinCond.eliminateDuplicates(session);
VoltXMLElement joinCondEl = new VoltXMLElement("joincond");
joinCondEl.children.add(joinCond.voltGetXML(session));
scan.children.add(joinCondEl);
}
if (whereCond != null) {
whereCond = whereCond.eliminateDuplicates(session);
VoltXMLElement whereCondEl = new VoltXMLElement("wherecond");
whereCondEl.children.add(whereCond.voltGetXML(session));
scan.children.add(whereCondEl);
}
return scan;
}
use of org.hsqldb_voltpatches.HSQLInterface.HSQLParseException in project voltdb by VoltDB.
the class StatementDML method voltAppendSortAndSlice.
/**
* Appends XML for ORDER BY/LIMIT/OFFSET to this statement's XML.
* */
private void voltAppendSortAndSlice(Session session, VoltXMLElement xml) throws HSQLParseException {
if (m_sortAndSlice == null || m_sortAndSlice == SortAndSlice.noSort) {
return;
}
// Is target a view?
if (targetTable.getBaseTable() != targetTable) {
// will be some more work to do to resolve columns in ORDER BY properly.
throw new HSQLParseException("DELETE with ORDER BY, LIMIT or OFFSET is currently unsupported on views.");
}
if (m_sortAndSlice.hasLimit() && !m_sortAndSlice.hasOrder()) {
throw new HSQLParseException("DELETE statement with LIMIT or OFFSET but no ORDER BY would produce " + "non-deterministic results. Please use an ORDER BY clause.");
} else if (m_sortAndSlice.hasOrder() && !m_sortAndSlice.hasLimit()) {
// we let this slide?
throw new HSQLParseException("DELETE statement with ORDER BY but no LIMIT or OFFSET is not allowed. " + "Consider removing the ORDER BY clause, as it has no effect here.");
}
List<VoltXMLElement> newElements = voltGetLimitOffsetXMLFromSortAndSlice(session, m_sortAndSlice);
// This code isn't shared with how SELECT's ORDER BY clauses are serialized since there's
// some extra work that goes on there to handle references to SELECT clauses aliases, etc.
HsqlArrayList exprList = m_sortAndSlice.exprList;
if (exprList != null) {
VoltXMLElement orderColumnsXml = new VoltXMLElement("ordercolumns");
for (int i = 0; i < exprList.size(); ++i) {
Expression e = (Expression) exprList.get(i);
VoltXMLElement elem = e.voltGetXML(session);
orderColumnsXml.children.add(elem);
}
newElements.add(orderColumnsXml);
}
xml.children.addAll(newElements);
}
Aggregations