Search in sources :

Example 1 with CacheUse

use of org.voltdb.PlannerStatsCollector.CacheUse 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)

Aggregations

HSQLParseException (org.hsqldb_voltpatches.HSQLInterface.HSQLParseException)1 ParameterSet (org.voltdb.ParameterSet)1 CacheUse (org.voltdb.PlannerStatsCollector.CacheUse)1 BoundPlan (org.voltdb.planner.BoundPlan)1 CompiledPlan (org.voltdb.planner.CompiledPlan)1 CorePlan (org.voltdb.planner.CorePlan)1 PlanningErrorException (org.voltdb.planner.PlanningErrorException)1 QueryPlanner (org.voltdb.planner.QueryPlanner)1 TrivialCostModel (org.voltdb.planner.TrivialCostModel)1