Search in sources :

Example 1 with StmtParameter

use of org.voltdb.catalog.StmtParameter in project voltdb by VoltDB.

the class ReportMaker method genrateStatementRow.

static String genrateStatementRow(CatalogMap<Table> tables, Procedure procedure, Statement statement) {
    // get the proc annotation which should exist or be created just before this is called
    ProcedureAnnotation procAnnotation = (ProcedureAnnotation) procedure.getAnnotation();
    assert (procAnnotation != null);
    StringBuilder sb = new StringBuilder();
    sb.append("        <tr class='primaryrow2'>");
    // name column
    String anchor = (procedure.getTypeName() + "-" + statement.getTypeName()).toLowerCase();
    sb.append("<td style='white-space: nowrap'><i id='p-" + anchor + "--icon' class='icon-chevron-right'></i> <a href='#' id='p-");
    sb.append(anchor).append("' class='togglex'>");
    sb.append(statement.getTypeName());
    sb.append("</a></td>");
    // sql column
    sb.append("<td><tt>");
    sb.append(escapeHtml4(statement.getSqltext()));
    sb.append("</td></tt>");
    // params column
    sb.append("<td>");
    List<StmtParameter> params = CatalogUtil.getSortedCatalogItems(statement.getParameters(), "index");
    List<String> paramTypes = new ArrayList<String>();
    for (StmtParameter param : params) {
        paramTypes.add(VoltType.get((byte) param.getJavatype()).name());
    }
    if (paramTypes.size() == 0) {
        sb.append("<i>None</i>");
    }
    sb.append(StringUtils.join(paramTypes, ", "));
    sb.append("</td>");
    // r/w column
    sb.append("<td>");
    if (statement.getReadonly()) {
        tag(sb, "success", "Read");
    } else {
        tag(sb, "warning", "Write");
    }
    sb.append("</td>");
    // attributes
    sb.append("<td>");
    if (!statement.getIscontentdeterministic() || !statement.getIsorderdeterministic()) {
        tag(sb, "inverse", "Determinism");
    }
    if (statement.getSeqscancount() > 0) {
        tag(sb, "important", "Scans");
    }
    sb.append("</td>");
    sb.append("</tr>\n");
    // BUILD THE DROPDOWN FOR THE PLAN/DETAIL TABLE
    sb.append("<tr class='dropdown2'><td colspan='5' id='p-" + procedure.getTypeName().toLowerCase() + "-" + statement.getTypeName().toLowerCase() + "--dropdown'>\n");
    sb.append("<div class='well well-small'><h4>Explain Plan:</h4>\n");
    String plan = escapeHtml4(Encoder.hexDecodeToString(statement.getExplainplan()));
    plan = plan.replace("\n", "<br/>");
    plan = plan.replace(" ", "&nbsp;");
    for (String tableName : statement.getTablesread().split(",")) {
        if (tableName.length() == 0) {
            continue;
        }
        Table t = tables.get(tableName);
        assert (t != null);
        TableAnnotation ta = (TableAnnotation) t.getAnnotation();
        assert (ta != null);
        ta.statementsThatReadThis.add(statement);
        ta.proceduresThatReadThis.add(procedure);
        procAnnotation.tablesRead.add(t);
        String uname = tableName.toUpperCase();
        String link = "\"<a href='#s-" + tableName + "'>" + uname + "</a>\"";
        plan = plan.replace("&quot;" + uname + "&quot;", link);
    }
    for (String tableName : statement.getTablesupdated().split(",")) {
        if (tableName.length() == 0) {
            continue;
        }
        Table t = tables.get(tableName);
        assert (t != null);
        TableAnnotation ta = (TableAnnotation) t.getAnnotation();
        assert (ta != null);
        ta.statementsThatUpdateThis.add(statement);
        ta.proceduresThatUpdateThis.add(procedure);
        procAnnotation.tablesUpdated.add(t);
        String uname = tableName.toUpperCase();
        String link = "\"<a href='#s-" + tableName + "'>" + uname + "</a>\"";
        plan = plan.replace("&quot;" + uname + "&quot;", link);
    }
    for (String tableDotIndexPair : statement.getIndexesused().split(",")) {
        if (tableDotIndexPair.length() == 0) {
            continue;
        }
        String[] parts = tableDotIndexPair.split("\\.", 2);
        assert (parts.length == 2);
        if (parts.length != 2) {
            continue;
        }
        String tableName = parts[0];
        String indexName = parts[1];
        Table t = tables.get(tableName);
        assert (t != null);
        Index i = t.getIndexes().get(indexName);
        assert (i != null);
        IndexAnnotation ia = (IndexAnnotation) i.getAnnotation();
        if (ia == null) {
            ia = new IndexAnnotation();
            i.setAnnotation(ia);
        }
        ia.proceduresThatUseThis.add(procedure);
        procAnnotation.indexesUsed.add(i);
        String uindexName = indexName.toUpperCase();
        String link = "\"<a href='#s-" + tableName + "-" + indexName + "'>" + uindexName + "</a>\"";
        plan = plan.replace("&quot;" + uindexName + "&quot;", link);
    }
    sb.append("<tt>").append(plan).append("</tt>");
    sb.append("</div>\n");
    sb.append("</td></tr>\n");
    return sb.toString();
}
Also used : StmtParameter(org.voltdb.catalog.StmtParameter) Table(org.voltdb.catalog.Table) ArrayList(java.util.ArrayList) Index(org.voltdb.catalog.Index)

Example 2 with StmtParameter

use of org.voltdb.catalog.StmtParameter in project voltdb by VoltDB.

the class ProcedureCompiler method compileSingleStmtProcedure.

static void compileSingleStmtProcedure(VoltCompiler compiler, HSQLInterface hsql, DatabaseEstimates estimates, Database db, ProcedureDescriptor procedureDescriptor) throws VoltCompiler.VoltCompilerException {
    final String className = procedureDescriptor.m_className;
    if (className.indexOf('@') != -1) {
        throw compiler.new VoltCompilerException("User procedure names can't contain \"@\".");
    }
    // get the short name of the class (no package if a user procedure)
    // use the Table.<builtin> name (allowing the period) if builtin.
    String shortName = className;
    if (procedureDescriptor.m_builtInStmt == false) {
        String[] parts = className.split("\\.");
        shortName = parts[parts.length - 1];
    }
    // add an entry to the catalog (using the full className)
    final Procedure procedure = db.getProcedures().add(shortName);
    for (String groupName : procedureDescriptor.m_authGroups) {
        final Group group = db.getGroups().get(groupName);
        if (group == null) {
            throw compiler.new VoltCompilerException("Procedure " + className + " allows access by a role " + groupName + " that does not exist");
        }
        final GroupRef groupRef = procedure.getAuthgroups().add(groupName);
        groupRef.setGroup(group);
    }
    procedure.setClassname(className);
    // sysprocs don't use the procedure compiler
    procedure.setSystemproc(false);
    procedure.setDefaultproc(procedureDescriptor.m_builtInStmt);
    procedure.setHasjava(false);
    procedure.setTransactional(true);
    // get the annotation
    // first try to get one that has been passed from the compiler
    ProcInfoData info = compiler.getProcInfoOverride(shortName);
    // and create a ProcInfo.Data instance for it
    if (info == null) {
        info = new ProcInfoData();
        if (procedureDescriptor.m_partitionString != null) {
            info.partitionInfo = procedureDescriptor.m_partitionString;
            info.singlePartition = true;
        }
    }
    assert (info != null);
    // ADD THE STATEMENT
    // add the statement to the catalog
    Statement catalogStmt = procedure.getStatements().add(VoltDB.ANON_STMT_NAME);
    // compile the statement
    StatementPartitioning partitioning = info.singlePartition ? StatementPartitioning.forceSP() : StatementPartitioning.forceMP();
    // default to FASTER detmode because stmt procs can't feed read output into writes
    StatementCompiler.compileFromSqlTextAndUpdateCatalog(compiler, hsql, db, estimates, catalogStmt, procedureDescriptor.m_singleStmt, procedureDescriptor.m_joinOrder, DeterminismMode.FASTER, partitioning);
    // if the single stmt is not read only, then the proc is not read only
    boolean procHasWriteStmts = (catalogStmt.getReadonly() == false);
    // set the read onlyness of a proc
    procedure.setReadonly(procHasWriteStmts == false);
    int seqs = catalogStmt.getSeqscancount();
    procedure.setHasseqscans(seqs > 0);
    // set procedure parameter types
    CatalogMap<ProcParameter> params = procedure.getParameters();
    CatalogMap<StmtParameter> stmtParams = catalogStmt.getParameters();
    // set the procedure parameter types from the statement parameter types
    int paramCount = 0;
    for (StmtParameter stmtParam : CatalogUtil.getSortedCatalogItems(stmtParams, "index")) {
        // name each parameter "param1", "param2", etc...
        ProcParameter procParam = params.add("param" + String.valueOf(paramCount));
        procParam.setIndex(stmtParam.getIndex());
        procParam.setIsarray(stmtParam.getIsarray());
        procParam.setType(stmtParam.getJavatype());
        paramCount++;
    }
    // parse the procinfo
    procedure.setSinglepartition(info.singlePartition);
    if (info.singlePartition) {
        parsePartitionInfo(compiler, db, procedure, info.partitionInfo);
        if (procedure.getPartitionparameter() >= params.size()) {
            String msg = "PartitionInfo parameter not a valid parameter for procedure: " + procedure.getClassname();
            throw compiler.new VoltCompilerException(msg);
        }
    // TODO: The planner does not currently validate that a single-statement plan declared as single-partition correctly uses
    // the designated parameter as a partitioning filter, maybe some day.
    // In theory, the PartitioningForStatement would confirm the use of (only) a parameter as a partition key --
    // or if the partition key was determined to be some other hard-coded constant (expression?) it might display a warning
    // message that the passed parameter is assumed to be equal to that constant (expression).
    } else {
        if (partitioning.getCountOfIndependentlyPartitionedTables() == 1) {
            AbstractExpression statementPartitionExpression = partitioning.singlePartitioningExpressionForReport();
            if (statementPartitionExpression != null) {
                // The planner has uncovered an overlooked opportunity to run the statement SP.
                String msg = "This procedure " + shortName + " would benefit from being partitioned, by ";
                String tableName = "tableName", partitionColumnName = "partitionColumnName";
                try {
                    assert (partitioning.getFullColumnName() != null);
                    String[] array = partitioning.getFullColumnName().split("\\.");
                    tableName = array[0];
                    partitionColumnName = array[1];
                } catch (Exception ex) {
                }
                if (statementPartitionExpression instanceof ParameterValueExpression) {
                    paramCount = ((ParameterValueExpression) statementPartitionExpression).getParameterIndex();
                } else {
                    String valueDescription = null;
                    Object partitionValue = partitioning.getInferredPartitioningValue();
                    if (partitionValue == null) {
                        // Statement partitioned on a runtime constant. This is likely to be cryptic, but hopefully gets the idea across.
                        valueDescription = "of " + statementPartitionExpression.explain("");
                    } else {
                        // A simple constant value COULD have been a parameter.
                        valueDescription = partitionValue.toString();
                    }
                    msg += "adding a parameter to be passed the value " + valueDescription + " and ";
                }
                msg += "adding a 'PARTITION ON TABLE " + tableName + " COLUMN " + partitionColumnName + " PARAMETER " + paramCount + "' clause to the " + "CREATE PROCEDURE statement. or using a separate PARTITION PROCEDURE statement";
                compiler.addWarn(msg);
            }
        }
    }
}
Also used : Group(org.voltdb.catalog.Group) Statement(org.voltdb.catalog.Statement) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException) VoltTypeException(org.voltdb.VoltTypeException) StmtParameter(org.voltdb.catalog.StmtParameter) AbstractExpression(org.voltdb.expressions.AbstractExpression) ProcInfoData(org.voltdb.ProcInfoData) StatementPartitioning(org.voltdb.planner.StatementPartitioning) VoltProcedure(org.voltdb.VoltProcedure) VoltNonTransactionalProcedure(org.voltdb.VoltNonTransactionalProcedure) Procedure(org.voltdb.catalog.Procedure) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException) GroupRef(org.voltdb.catalog.GroupRef) ParameterValueExpression(org.voltdb.expressions.ParameterValueExpression) ProcParameter(org.voltdb.catalog.ProcParameter)

Example 3 with StmtParameter

use of org.voltdb.catalog.StmtParameter in project voltdb by VoltDB.

the class PlannerTestAideDeCamp method compile.

/**
     * Compile and cache the statement and plan and return the final plan graph.
     */
private List<AbstractPlanNode> compile(String sql, int paramCount, String joinOrder, boolean inferPartitioning, boolean forceSingle, DeterminismMode detMode) {
    String stmtLabel = "stmt-" + String.valueOf(compileCounter++);
    Statement catalogStmt = proc.getStatements().add(stmtLabel);
    catalogStmt.setSqltext(sql);
    catalogStmt.setSinglepartition(forceSingle);
    // determine the type of the query
    QueryType qtype = QueryType.SELECT;
    catalogStmt.setReadonly(true);
    if (sql.toLowerCase().startsWith("insert")) {
        qtype = QueryType.INSERT;
        catalogStmt.setReadonly(false);
    }
    if (sql.toLowerCase().startsWith("update")) {
        qtype = QueryType.UPDATE;
        catalogStmt.setReadonly(false);
    }
    if (sql.toLowerCase().startsWith("delete")) {
        qtype = QueryType.DELETE;
        catalogStmt.setReadonly(false);
    }
    catalogStmt.setQuerytype(qtype.getValue());
    // name will look like "basename-stmt-#"
    String name = catalogStmt.getParent().getTypeName() + "-" + catalogStmt.getTypeName();
    DatabaseEstimates estimates = new DatabaseEstimates();
    TrivialCostModel costModel = new TrivialCostModel();
    StatementPartitioning partitioning;
    if (inferPartitioning) {
        partitioning = StatementPartitioning.inferPartitioning();
    } else if (forceSingle) {
        partitioning = StatementPartitioning.forceSP();
    } else {
        partitioning = StatementPartitioning.forceMP();
    }
    String procName = catalogStmt.getParent().getTypeName();
    QueryPlanner planner = new QueryPlanner(sql, stmtLabel, procName, db, partitioning, hsql, estimates, false, StatementCompiler.DEFAULT_MAX_JOIN_TABLES, costModel, null, joinOrder, detMode);
    CompiledPlan plan = null;
    planner.parse();
    plan = planner.plan();
    assert (plan != null);
    // Partitioning optionally inferred from the planning process.
    if (partitioning.isInferred()) {
        catalogStmt.setSinglepartition(partitioning.isInferredSingle());
    }
    // We will need to update the system catalogs with this new information
    for (int i = 0; i < plan.parameters.length; ++i) {
        StmtParameter catalogParam = catalogStmt.getParameters().add(String.valueOf(i));
        ParameterValueExpression pve = plan.parameters[i];
        catalogParam.setJavatype(pve.getValueType().getValue());
        catalogParam.setIsarray(pve.getParamIsVector());
        catalogParam.setIndex(i);
    }
    List<PlanNodeList> nodeLists = new ArrayList<>();
    nodeLists.add(new PlanNodeList(plan.rootPlanGraph));
    if (plan.subPlanGraph != null) {
        nodeLists.add(new PlanNodeList(plan.subPlanGraph));
    }
    // Now update our catalog information
    // HACK: We're using the node_tree's hashCode() as it's name. It would be really
    //     nice if the Catalog code give us an guid without needing a name first...
    String json = null;
    try {
        JSONObject jobj = new JSONObject(nodeLists.get(0).toJSONString());
        json = jobj.toString(4);
    } catch (JSONException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
        System.exit(-1);
        return null;
    }
    //
    try {
        BuildDirectoryUtils.writeFile("statement-plans", name + "_json.txt", json, true);
        BuildDirectoryUtils.writeFile("statement-plans", name + ".dot", nodeLists.get(0).toDOTString("name"), true);
    } catch (Exception e) {
        e.printStackTrace();
    }
    List<AbstractPlanNode> plannodes = new ArrayList<>();
    for (PlanNodeList nodeList : nodeLists) {
        plannodes.add(nodeList.getRootPlanNode());
    }
    m_currentPlan = plan;
    return plannodes;
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) Statement(org.voltdb.catalog.Statement) ArrayList(java.util.ArrayList) JSONException(org.json_voltpatches.JSONException) PlanNodeList(org.voltdb.plannodes.PlanNodeList) JSONException(org.json_voltpatches.JSONException) StmtParameter(org.voltdb.catalog.StmtParameter) JSONObject(org.json_voltpatches.JSONObject) ParameterValueExpression(org.voltdb.expressions.ParameterValueExpression) QueryType(org.voltdb.types.QueryType) DatabaseEstimates(org.voltdb.compiler.DatabaseEstimates)

Example 4 with StmtParameter

use of org.voltdb.catalog.StmtParameter in project voltdb by VoltDB.

the class ProcedureRunner method initSQLStmt.

public void initSQLStmt(SQLStmt stmt, Statement catStmt) {
    int fragCount = catStmt.getFragments().size();
    for (PlanFragment frag : catStmt.getFragments()) {
        byte[] planHash = Encoder.hexDecode(frag.getPlanhash());
        byte[] plan = Encoder.decodeBase64AndDecompressToBytes(frag.getPlannodetree());
        long id = ActivePlanRepository.loadOrAddRefPlanFragment(planHash, plan, catStmt.getSqltext());
        boolean transactional = frag.getNontransactional() == false;
        SQLStmt.Frag stmtFrag = new SQLStmt.Frag(id, planHash, transactional);
        if (fragCount == 1 || frag.getHasdependencies()) {
            stmt.aggregator = stmtFrag;
        } else {
            stmt.collector = stmtFrag;
        }
    }
    stmt.isReadOnly = catStmt.getReadonly();
    stmt.isReplicatedTableDML = catStmt.getReplicatedtabledml();
    stmt.site = m_site;
    int numStatementParamTypes = catStmt.getParameters().size();
    stmt.statementParamTypes = new byte[numStatementParamTypes];
    for (StmtParameter param : catStmt.getParameters()) {
        int index = param.getIndex();
        // Array-typed params currently only arise from in-lists.
        // Tweak the parameter's expected type accordingly.
        VoltType expectType = VoltType.get((byte) param.getJavatype());
        if (param.getIsarray()) {
            if (expectType == VoltType.STRING) {
                expectType = VoltType.INLIST_OF_STRING;
            } else {
                expectType = VoltType.INLIST_OF_BIGINT;
            }
        }
        stmt.statementParamTypes[index] = expectType.getValue();
    }
}
Also used : StmtParameter(org.voltdb.catalog.StmtParameter) PlanFragment(org.voltdb.catalog.PlanFragment)

Example 5 with StmtParameter

use of org.voltdb.catalog.StmtParameter in project voltdb by VoltDB.

the class StatementCompiler method compileStatementAndUpdateCatalog.

/**
     * This static method conveniently does a few things for its caller:
     * - Formats the statement by replacing newlines with spaces
     *     and appends a semicolon if needed
     * - Updates the catalog Statement with metadata about the statement
     * - Plans the statement and puts the serialized plan in the catalog Statement
     * - Updates the catalog Statment with info about the statement's parameters
     * Upon successful completion, catalog statement will have been updated with
     * plan fragments needed to execute the statement.
     *
     * @param  compiler     The VoltCompiler instance
     * @param  hsql         Pass through parameter to QueryPlanner
     * @param  catalog      Pass through parameter to QueryPlanner
     * @param  db           Pass through parameter to QueryPlanner
     * @param  estimates    Pass through parameter to QueryPlanner
     * @param  catalogStmt  Catalog statement to be updated with plan
     * @param  xml          XML for statement, if it has been previously parsed
     *                      (may be null)
     * @param  stmt         Text of statement to be compiled
     * @param  joinOrder    Pass through parameter to QueryPlanner
     * @param  detMode      Pass through parameter to QueryPlanner
     * @param  partitioning Partition info for statement
    */
static boolean compileStatementAndUpdateCatalog(VoltCompiler compiler, HSQLInterface hsql, Database db, DatabaseEstimates estimates, Statement catalogStmt, VoltXMLElement xml, String stmt, String joinOrder, DeterminismMode detMode, StatementPartitioning partitioning) throws VoltCompiler.VoltCompilerException {
    // Cleanup whitespace newlines for catalog compatibility
    // and to make statement parsing easier.
    stmt = stmt.replaceAll("\n", " ");
    stmt = stmt.trim();
    compiler.addInfo("Compiling Statement: " + stmt);
    // put the data in the catalog that we have
    if (!stmt.endsWith(";")) {
        stmt += ";";
    }
    // if this key + sql is the same, then a cached stmt can be used
    String keyPrefix = compiler.getKeyPrefix(partitioning, detMode, joinOrder);
    // if the key is cache-able, look for a previous statement
    if (keyPrefix != null) {
        Statement previousStatement = compiler.getCachedStatement(keyPrefix, stmt);
        // check if the stmt exists and if it's the same sql text
        if (previousStatement != null) {
            catalogStmt.setAnnotation(previousStatement.getAnnotation());
            catalogStmt.setAttachment(previousStatement.getAttachment());
            catalogStmt.setCachekeyprefix(previousStatement.getCachekeyprefix());
            catalogStmt.setCost(previousStatement.getCost());
            catalogStmt.setExplainplan(previousStatement.getExplainplan());
            catalogStmt.setIscontentdeterministic(previousStatement.getIscontentdeterministic());
            catalogStmt.setIsorderdeterministic(previousStatement.getIsorderdeterministic());
            catalogStmt.setNondeterminismdetail(previousStatement.getNondeterminismdetail());
            catalogStmt.setQuerytype(previousStatement.getQuerytype());
            catalogStmt.setReadonly(previousStatement.getReadonly());
            catalogStmt.setReplicatedtabledml(previousStatement.getReplicatedtabledml());
            catalogStmt.setSeqscancount(previousStatement.getSeqscancount());
            catalogStmt.setSinglepartition(previousStatement.getSinglepartition());
            catalogStmt.setSqltext(previousStatement.getSqltext());
            catalogStmt.setTablesread(previousStatement.getTablesread());
            catalogStmt.setTablesupdated(previousStatement.getTablesupdated());
            catalogStmt.setIndexesused(previousStatement.getIndexesused());
            for (StmtParameter oldSp : previousStatement.getParameters()) {
                StmtParameter newSp = catalogStmt.getParameters().add(oldSp.getTypeName());
                newSp.setAnnotation(oldSp.getAnnotation());
                newSp.setAttachment(oldSp.getAttachment());
                newSp.setIndex(oldSp.getIndex());
                newSp.setIsarray(oldSp.getIsarray());
                newSp.setJavatype(oldSp.getJavatype());
                newSp.setSqltype(oldSp.getSqltype());
            }
            for (PlanFragment oldFrag : previousStatement.getFragments()) {
                PlanFragment newFrag = catalogStmt.getFragments().add(oldFrag.getTypeName());
                newFrag.setAnnotation(oldFrag.getAnnotation());
                newFrag.setAttachment(oldFrag.getAttachment());
                newFrag.setHasdependencies(oldFrag.getHasdependencies());
                newFrag.setMultipartition(oldFrag.getMultipartition());
                newFrag.setNontransactional(oldFrag.getNontransactional());
                newFrag.setPlanhash(oldFrag.getPlanhash());
                newFrag.setPlannodetree(oldFrag.getPlannodetree());
            }
            return true;
        }
    }
    // determine the type of the query
    QueryType qtype = QueryType.getFromSQL(stmt);
    catalogStmt.setReadonly(qtype.isReadOnly());
    catalogStmt.setQuerytype(qtype.getValue());
    // might be null if not cacheable
    catalogStmt.setCachekeyprefix(keyPrefix);
    catalogStmt.setSqltext(stmt);
    catalogStmt.setSinglepartition(partitioning.wasSpecifiedAsSingle());
    String name = catalogStmt.getParent().getTypeName() + "-" + catalogStmt.getTypeName();
    String sql = catalogStmt.getSqltext();
    String stmtName = catalogStmt.getTypeName();
    String procName = catalogStmt.getParent().getTypeName();
    TrivialCostModel costModel = new TrivialCostModel();
    CompiledPlan plan = null;
    QueryPlanner planner = new QueryPlanner(sql, stmtName, procName, db, partitioning, hsql, estimates, false, DEFAULT_MAX_JOIN_TABLES, costModel, null, joinOrder, detMode);
    try {
        try {
            if (xml != null) {
                planner.parseFromXml(xml);
            } else {
                planner.parse();
            }
            plan = planner.plan();
            assert (plan != null);
        } catch (PlanningErrorException e) {
            // These are normal expectable errors -- don't normally need a stack-trace.
            String msg = "Failed to plan for statement (" + catalogStmt.getTypeName() + ") \"" + catalogStmt.getSqltext() + "\".";
            if (e.getMessage() != null) {
                msg += " Error: \"" + e.getMessage() + "\"";
            }
            throw compiler.new VoltCompilerException(msg);
        } catch (Exception e) {
            e.printStackTrace();
            throw compiler.new VoltCompilerException("Failed to plan for stmt: " + catalogStmt.getTypeName());
        }
        // There is a hard-coded limit to the number of parameters that can be passed to the EE.
        if (plan.parameters.length > CompiledPlan.MAX_PARAM_COUNT) {
            throw compiler.new VoltCompilerException("The statement's parameter count " + plan.parameters.length + " must not exceed the maximum " + CompiledPlan.MAX_PARAM_COUNT);
        }
        // Check order and content determinism before accessing the detail which
        // it caches.
        boolean orderDeterministic = plan.isOrderDeterministic();
        catalogStmt.setIsorderdeterministic(orderDeterministic);
        boolean contentDeterministic = plan.isContentDeterministic() && (orderDeterministic || !plan.hasLimitOrOffset());
        catalogStmt.setIscontentdeterministic(contentDeterministic);
        String nondeterminismDetail = plan.nondeterminismDetail();
        catalogStmt.setNondeterminismdetail(nondeterminismDetail);
        catalogStmt.setSeqscancount(plan.countSeqScans());
        // We will need to update the system catalogs with this new information
        for (int i = 0; i < plan.parameters.length; ++i) {
            StmtParameter catalogParam = catalogStmt.getParameters().add(String.valueOf(i));
            catalogParam.setJavatype(plan.parameters[i].getValueType().getValue());
            catalogParam.setIsarray(plan.parameters[i].getParamIsVector());
            catalogParam.setIndex(i);
        }
        catalogStmt.setReplicatedtabledml(plan.replicatedTableDML);
        // output the explained plan to disk (or caller) for debugging
        // Initial capacity estimate.
        StringBuilder planDescription = new StringBuilder(1000);
        planDescription.append("SQL: ").append(plan.sql);
        // Cost seems to only confuse people who don't understand how this number is used/generated.
        if (VoltCompiler.DEBUG_MODE) {
            planDescription.append("\nCOST: ").append(plan.cost);
        }
        planDescription.append("\nPLAN:\n");
        planDescription.append(plan.explainedPlan);
        String planString = planDescription.toString();
        // only write to disk if compiler is in standalone mode
        if (compiler.standaloneCompiler) {
            BuildDirectoryUtils.writeFile(null, name + ".txt", planString, false);
        }
        compiler.captureDiagnosticContext(planString);
        // build usage links for report generation and put them in the catalog
        CatalogUtil.updateUsageAnnotations(db, catalogStmt, plan.rootPlanGraph, plan.subPlanGraph);
        // set the explain plan output into the catalog (in hex) for reporting
        catalogStmt.setExplainplan(Encoder.hexEncode(plan.explainedPlan));
        // compute a hash of the plan
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            assert (false);
            // should never happen with healthy jvm
            System.exit(-1);
        }
        // Now update our catalog information
        PlanFragment planFragment = catalogStmt.getFragments().add("0");
        planFragment.setHasdependencies(plan.subPlanGraph != null);
        // mark a fragment as non-transactional if it never touches a persistent table
        planFragment.setNontransactional(!fragmentReferencesPersistentTable(plan.rootPlanGraph));
        planFragment.setMultipartition(plan.subPlanGraph != null);
        byte[] planBytes = writePlanBytes(compiler, planFragment, plan.rootPlanGraph);
        md.update(planBytes, 0, planBytes.length);
        // compute the 40 bytes of hex from the 20 byte sha1 hash of the plans
        md.reset();
        md.update(planBytes);
        planFragment.setPlanhash(Encoder.hexEncode(md.digest()));
        if (plan.subPlanGraph != null) {
            planFragment = catalogStmt.getFragments().add("1");
            planFragment.setHasdependencies(false);
            planFragment.setNontransactional(false);
            planFragment.setMultipartition(true);
            byte[] subBytes = writePlanBytes(compiler, planFragment, plan.subPlanGraph);
            // compute the 40 bytes of hex from the 20 byte sha1 hash of the plans
            md.reset();
            md.update(subBytes);
            planFragment.setPlanhash(Encoder.hexEncode(md.digest()));
        }
        // Planner should have rejected with an exception any statement with an unrecognized type.
        int validType = catalogStmt.getQuerytype();
        assert (validType != QueryType.INVALID.getValue());
        return false;
    } catch (StackOverflowError error) {
        String msg = "Failed to plan for statement (" + catalogStmt.getTypeName() + ") \"" + catalogStmt.getSqltext() + "\". Error: \"Encountered stack overflow error. " + "Try reducing the number of predicate expressions in the query.\"";
        throw compiler.new VoltCompilerException(msg);
    }
}
Also used : CompiledPlan(org.voltdb.planner.CompiledPlan) PlanningErrorException(org.voltdb.planner.PlanningErrorException) Statement(org.voltdb.catalog.Statement) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) PlanFragment(org.voltdb.catalog.PlanFragment) QueryPlanner(org.voltdb.planner.QueryPlanner) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException) PlanningErrorException(org.voltdb.planner.PlanningErrorException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) StmtParameter(org.voltdb.catalog.StmtParameter) TrivialCostModel(org.voltdb.planner.TrivialCostModel) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException) MessageDigest(java.security.MessageDigest) QueryType(org.voltdb.types.QueryType)

Aggregations

StmtParameter (org.voltdb.catalog.StmtParameter)6 Statement (org.voltdb.catalog.Statement)4 PlanFragment (org.voltdb.catalog.PlanFragment)3 ParameterValueExpression (org.voltdb.expressions.ParameterValueExpression)3 QueryType (org.voltdb.types.QueryType)3 MessageDigest (java.security.MessageDigest)2 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)2 ArrayList (java.util.ArrayList)2 ProcParameter (org.voltdb.catalog.ProcParameter)2 Procedure (org.voltdb.catalog.Procedure)2 Table (org.voltdb.catalog.Table)2 VoltCompilerException (org.voltdb.compiler.VoltCompiler.VoltCompilerException)2 CompiledPlan (org.voltdb.planner.CompiledPlan)2 StatementPartitioning (org.voltdb.planner.StatementPartitioning)2 JSONException (org.json_voltpatches.JSONException)1 JSONObject (org.json_voltpatches.JSONObject)1 ProcedurePartitionInfo (org.voltdb.CatalogContext.ProcedurePartitionInfo)1 ProcInfoData (org.voltdb.ProcInfoData)1 VoltNonTransactionalProcedure (org.voltdb.VoltNonTransactionalProcedure)1 VoltProcedure (org.voltdb.VoltProcedure)1