Search in sources :

Example 36 with VoltCompilerException

use of org.voltdb.compiler.VoltCompiler.VoltCompilerException 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)

Example 37 with VoltCompilerException

use of org.voltdb.compiler.VoltCompiler.VoltCompilerException in project voltdb by VoltDB.

the class CreateRole method processStatement.

@Override
protected boolean processStatement(DDLStatement ddlStatement, Database db, DdlProceduresToLoad whichProcs) throws VoltCompilerException {
    // matches if it is CREATE ROLE [WITH <permission> [, <permission> ...]]
    // group 1 is role name
    // group 2 is comma-separated permission list or null if there is no WITH clause
    Matcher statementMatcher = SQLParser.matchCreateRole(ddlStatement.statement);
    if (!statementMatcher.matches()) {
        return false;
    }
    String roleName = statementMatcher.group(1).toLowerCase();
    CatalogMap<Group> groupMap = db.getGroups();
    if (groupMap.get(roleName) != null) {
        throw m_compiler.new VoltCompilerException(String.format("Role name \"%s\" in CREATE ROLE statement already exists.", roleName));
    }
    Group catGroup = groupMap.add(roleName);
    if (statementMatcher.group(2) != null) {
        try {
            EnumSet<Permission> permset = Permission.getPermissionsFromAliases(Arrays.asList(StringUtils.split(statementMatcher.group(2), ',')));
            Permission.setPermissionsInGroup(catGroup, permset);
        } catch (IllegalArgumentException iaex) {
            throw m_compiler.new VoltCompilerException(String.format("Invalid permission \"%s\" in CREATE ROLE statement: \"%s\", " + "available permissions: %s", iaex.getMessage(), // remove trailing semicolon
            ddlStatement.statement.substring(0, ddlStatement.statement.length() - 1), Permission.toListString()));
        }
    }
    return true;
}
Also used : Group(org.voltdb.catalog.Group) Matcher(java.util.regex.Matcher) Permission(org.voltdb.common.Permission) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException)

Example 38 with VoltCompilerException

use of org.voltdb.compiler.VoltCompiler.VoltCompilerException in project voltdb by VoltDB.

the class DropFunction method processStatement.

@Override
protected boolean processStatement(DDLStatement ddlStatement, Database db, DdlProceduresToLoad whichProcs) throws VoltCompilerException {
    // Matches if it is DROP FUNCTION <name>
    Matcher statementMatcher = SQLParser.matchDropFunction(ddlStatement.statement);
    if (!statementMatcher.matches()) {
        return false;
    }
    String functionName = checkIdentifierStart(statementMatcher.group(1), ddlStatement.statement).toLowerCase();
    boolean ifExists = statementMatcher.group(2) != null;
    CatalogMap<Function> functions = db.getFunctions();
    if (functions.get(functionName) != null) {
        functions.delete(functionName);
        FunctionForVoltDB.deregisterUserDefinedFunction(functionName);
    } else {
        if (!ifExists) {
            throw m_compiler.new VoltCompilerException(String.format("Function name \"%s\" in DROP FUNCTION statement does not exist.", functionName));
        }
    }
    return true;
}
Also used : Function(org.voltdb.catalog.Function) Matcher(java.util.regex.Matcher) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException)

Aggregations

VoltCompilerException (org.voltdb.compiler.VoltCompiler.VoltCompilerException)38 Matcher (java.util.regex.Matcher)15 Constraint (org.voltdb.catalog.Constraint)11 VoltXMLElement (org.hsqldb_voltpatches.VoltXMLElement)10 Column (org.voltdb.catalog.Column)7 AbstractExpression (org.voltdb.expressions.AbstractExpression)7 VoltType (org.voltdb.VoltType)6 Index (org.voltdb.catalog.Index)5 IOException (java.io.IOException)4 HSQLParseException (org.hsqldb_voltpatches.HSQLInterface.HSQLParseException)4 JSONException (org.json_voltpatches.JSONException)4 VoltTypeException (org.voltdb.VoltTypeException)4 Group (org.voltdb.catalog.Group)4 ProcParameter (org.voltdb.catalog.ProcParameter)4 Statement (org.voltdb.catalog.Statement)4 Table (org.voltdb.catalog.Table)4 Method (java.lang.reflect.Method)3 ArrayList (java.util.ArrayList)3 ColumnRef (org.voltdb.catalog.ColumnRef)3 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)3