Search in sources :

Example 1 with HSQLParseException

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);
        }
    }
}
Also used : CompiledPlan(org.voltdb.planner.CompiledPlan) ParameterSet(org.voltdb.ParameterSet) PlanningErrorException(org.voltdb.planner.PlanningErrorException) CacheUse(org.voltdb.PlannerStatsCollector.CacheUse) CorePlan(org.voltdb.planner.CorePlan) QueryPlanner(org.voltdb.planner.QueryPlanner) PlanningErrorException(org.voltdb.planner.PlanningErrorException) HSQLParseException(org.hsqldb_voltpatches.HSQLInterface.HSQLParseException) HSQLParseException(org.hsqldb_voltpatches.HSQLInterface.HSQLParseException) TrivialCostModel(org.voltdb.planner.TrivialCostModel) BoundPlan(org.voltdb.planner.BoundPlan)

Example 2 with HSQLParseException

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;
    }
}
Also used : TimestampData(org.hsqldb_voltpatches.types.TimestampData) BigDecimal(java.math.BigDecimal) HSQLParseException(org.hsqldb_voltpatches.HSQLInterface.HSQLParseException) NumberType(org.hsqldb_voltpatches.types.NumberType) BinaryData(org.hsqldb_voltpatches.types.BinaryData)

Example 3 with HSQLParseException

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);
        }
    }
}
Also used : HSQLDDLInfo(org.hsqldb_voltpatches.HSQLDDLInfo) VoltXMLDiff(org.hsqldb_voltpatches.VoltXMLElement.VoltXMLDiff) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException) HSQLParseException(org.hsqldb_voltpatches.HSQLInterface.HSQLParseException)

Example 4 with HSQLParseException

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;
}
Also used : Index(org.hsqldb_voltpatches.index.Index) HSQLParseException(org.hsqldb_voltpatches.HSQLInterface.HSQLParseException)

Example 5 with HSQLParseException

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);
}
Also used : HsqlArrayList(org.hsqldb_voltpatches.lib.HsqlArrayList) HSQLParseException(org.hsqldb_voltpatches.HSQLInterface.HSQLParseException)

Aggregations

HSQLParseException (org.hsqldb_voltpatches.HSQLInterface.HSQLParseException)13 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 URL (java.net.URL)2 ArrayList (java.util.ArrayList)2 SimpleColumnContext (org.hsqldb_voltpatches.Expression.SimpleColumnContext)2 VoltXMLElement (org.hsqldb_voltpatches.VoltXMLElement)2 VoltCompilerException (org.voltdb.compiler.VoltCompiler.VoltCompilerException)2 CompiledPlan (org.voltdb.planner.CompiledPlan)2 PlanningErrorException (org.voltdb.planner.PlanningErrorException)2 QueryPlanner (org.voltdb.planner.QueryPlanner)2 TrivialCostModel (org.voltdb.planner.TrivialCostModel)2 IOException (java.io.IOException)1 BigDecimal (java.math.BigDecimal)1 HashSet (java.util.HashSet)1 HSQLDDLInfo (org.hsqldb_voltpatches.HSQLDDLInfo)1 HSQLInterface (org.hsqldb_voltpatches.HSQLInterface)1 VoltXMLDiff (org.hsqldb_voltpatches.VoltXMLElement.VoltXMLDiff)1 Index (org.hsqldb_voltpatches.index.Index)1 HsqlArrayList (org.hsqldb_voltpatches.lib.HsqlArrayList)1 BinaryData (org.hsqldb_voltpatches.types.BinaryData)1