Examples of VoltCompilerException


Examples of org.voltdb.compiler.VoltCompiler.VoltCompilerException

        assert className != null && ! className.trim().isEmpty();

        String shortName = deriveShortProcedureName(className);

        if( m_procedureMap.containsKey(shortName)) {
            throw m_compiler.new VoltCompilerException(String.format(
                    "Procedure \"%s\" is already defined", className));
        }

        m_procedureMap.put(shortName, descriptor);
    }
View Full Code Here

Examples of org.voltdb.compiler.VoltCompiler.VoltCompilerException

        if( m_procedureMap.containsKey(shortName)) {
            m_procedureMap.remove(shortName);
        }
        else {
            throw m_compiler.new VoltCompilerException(String.format(
                    "Dropped Procedure \"%s\" is not defined", procName));
        }
    }
View Full Code Here

Examples of org.voltdb.compiler.VoltCompiler.VoltCompilerException

        assert procedureName != null && ! procedureName.trim().isEmpty();
        assert partitionInfo != null && ! partitionInfo.trim().isEmpty();

        ProcedureDescriptor descriptor = m_procedureMap.get(procedureName);
        if( descriptor == null) {
            throw m_compiler.new VoltCompilerException(String.format(
                    "Partition in referencing an undefined procedure \"%s\"",
                    procedureName));
        }

        // need to re-instantiate as descriptor fields are final
View Full Code Here

Examples of org.voltdb.compiler.VoltCompiler.VoltCompilerException

                if (procClass.getSimpleName().equals(procName) == false) {
                    msg = "Superclass " + procClass.getSimpleName() + " of procedure " +
                          procName + " contains a non-final SQLStmt field.";
                }
                if (compiler != null)
                    throw compiler.new VoltCompilerException(msg);
                else
                    new VoltLogger("HOST").warn(msg);
            }

            f.setAccessible(true);
View Full Code Here

Examples of org.voltdb.compiler.VoltCompiler.VoltCompilerException

                            // if not null, then we've got more than one run method
                            if (procMethod != null) {
                                String msg = "Procedure: " + shortName + " has multiple public run(...) methods. ";
                                msg += "Only a single run(...) method is supported.";
                                throw compiler.new VoltCompilerException(msg);
                            }

                            if (Modifier.isPublic(m.getModifiers())) {
                                // found it!
                                procMethod = m;
                            }
                            else {
                                compiler.addWarn("Procedure: " + shortName + " has non-public run(...) method.");
                            }
                        }
                    }
                    if (procMethod == null) {
                        String msg = "Procedure: " + shortName + " has no run(...) method.";
                        throw compiler.new VoltCompilerException(msg);
                    }
                    // check the return type of the run method
                    if ((procMethod.getReturnType() != VoltTable[].class) &&
                       (procMethod.getReturnType() != VoltTable.class) &&
                       (procMethod.getReturnType() != long.class) &&
                       (procMethod.getReturnType() != Long.class)) {

                        String msg = "Procedure: " + shortName + " has run(...) method that doesn't return long, Long, VoltTable or VoltTable[].";
                        throw compiler.new VoltCompilerException(msg);
                    }

                    builder.put("@run",procMethod);

                    return builder.build();
                }

                @Override
                public Map<String,Object> visitGroovy(Class<?> p) throws VoltCompilerException {
                    GroovyScriptProcedureDelegate scripDelegate;
                    try {
                        scripDelegate = new GroovyScriptProcedureDelegate(p);
                    } catch (GroovyScriptProcedureDelegate.SetupException tupex) {
                        throw compiler.new VoltCompilerException(tupex.getMessage());
                    }
                    return scripDelegate.getIntrospectedFields();
                }
            };
    };
View Full Code Here

Examples of org.voltdb.compiler.VoltCompiler.VoltCompilerException

        // add an entry to the catalog
        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 + " has a group " + 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(true);
        procedure.setLanguage(lang.name());
        ProcedureAnnotation pa = (ProcedureAnnotation) procedure.getAnnotation();
        if (pa == null) {
            pa = new ProcedureAnnotation();
            procedure.setAnnotation(pa);
        }
        if (procedureDescriptor.m_scriptImpl != null) {
            // This is a Groovy or other Java derived procedure and we need to add an annotation with
            // the script to the Procedure element in the Catalog
            pa.scriptImpl = procedureDescriptor.m_scriptImpl;
        }

        // get the annotation
        // first try to get one that has been passed from the compiler
        ProcInfoData info = compiler.getProcInfoOverride(shortName);
        // check if partition info was set in ddl
        ProcInfoData ddlInfo = null;
        if (procedureDescriptor.m_partitionString != null && ! procedureDescriptor.m_partitionString.trim().isEmpty()) {
            ddlInfo = new ProcInfoData();
            ddlInfo.partitionInfo = procedureDescriptor.m_partitionString;
            ddlInfo.singlePartition = true;
        }
        // then check for the usual one in the class itself
        // and create a ProcInfo.Data instance for it
        if (info == null) {
            info = new ProcInfoData();
            ProcInfo annotationInfo = procClass.getAnnotation(ProcInfo.class);
            // error out if partition info is present in both ddl and annotation
            if (annotationInfo != null) {
                if (ddlInfo != null) {
                    String msg = "Procedure: " + shortName + " has partition properties defined both in ";
                    msg += "class \"" + className + "\" and in the schema defintion file(s)";
                    throw compiler.new VoltCompilerException(msg);
                }
                // Prevent AutoGenerated DDL from including PARTITION PROCEDURE for this procedure.
                pa.classAnnotated = true;
                info.partitionInfo = annotationInfo.partitionInfo();
                info.singlePartition = annotationInfo.singlePartition();
            }
            else if (ddlInfo != null) {
                info = ddlInfo;
            }
        }
        else {
            pa.classAnnotated = true;
        }
        assert(info != null);

        // make sure multi-partition implies no partitoning info
        if (info.singlePartition == false) {
            if ((info.partitionInfo != null) && (info.partitionInfo.length() > 0)) {
                String msg = "Procedure: " + shortName + " is annotated as multi-partition";
                msg += " but partitionInfo has non-empty value: \"" + info.partitionInfo + "\"";
                throw compiler.new VoltCompilerException(msg);
            }
        }

        // track if there are any writer statements and/or sequential scans and/or an overlooked common partitioning parameter
        boolean procHasWriteStmts = false;
        boolean procHasSeqScans = false;
        // procWantsCommonPartitioning == true but commonPartitionExpression == null signifies a proc
        // for which the planner was requested to attempt to find an SP plan, but that was not possible
        // -- it had a replicated write or it had one or more partitioned reads that were not all
        // filtered by the same partition key value -- so it was planned as an MP proc.
        boolean procWantsCommonPartitioning = true;
        AbstractExpression commonPartitionExpression = null;
        String exampleSPstatement = null;
        Object exampleSPvalue = null;

        // iterate through the fields and get valid sql statements
        Map<String, Object> fields = lang.accept(procedureIntrospector(compiler), procClass);

        // determine if proc is read or read-write by checking if the proc contains any write sql stmts
        boolean readWrite = false;
        for (Object field : fields.values()) {
            if (!(field instanceof SQLStmt)) continue;
            SQLStmt stmt = (SQLStmt)field;
            QueryType qtype = QueryType.getFromSQL(stmt.getText());
            if (!qtype.isReadOnly()) {
                readWrite = true;
                break;
            }
        }

        // default to FASTER determinism mode, which may favor non-deterministic plans
        // but if it's a read-write proc, use a SAFER planning mode wrt determinism.
        final DeterminismMode detMode = readWrite ? DeterminismMode.SAFER : DeterminismMode.FASTER;

        for (Entry<String, Object> entry : fields.entrySet()) {
            if (!(entry.getValue() instanceof SQLStmt)) continue;

            String stmtName = entry.getKey();
            SQLStmt stmt = (SQLStmt)entry.getValue();

            // add the statement to the catalog
            Statement catalogStmt = procedure.getStatements().add(stmtName);

            // compile the statement
            StatementPartitioning partitioning =
                info.singlePartition ? StatementPartitioning.forceSP() :
                                       StatementPartitioning.forceMP();
            StatementCompiler.compile(compiler, hsql, catalog, db,
                    estimates, catalogStmt, stmt.getText(), stmt.getJoinOrder(),
                    detMode, partitioning);

            if (partitioning.wasSpecifiedAsSingle()) {
                procWantsCommonPartitioning = false; // Don't try to infer what's already been asserted.
                // The planner does not currently attempt to second-guess a plan declared as single-partition, 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 constant (expression?) it might display an informational
                // message that the passed parameter is assumed to be equal to the hard-coded partition key constant (expression).

                // Validate any inferred statement partitioning given the statement's possible usage, until a contradiction is found.
            }
            else if (procWantsCommonPartitioning) {
                // Only consider statements that are capable of running SP with a partitioning parameter that does not seem to
                // conflict with the partitioning of prior statements.
                if (partitioning.getCountOfIndependentlyPartitionedTables() == 1) {
                    AbstractExpression statementPartitionExpression = partitioning.singlePartitioningExpressionForReport();
                    if (statementPartitionExpression != null) {
                        if (commonPartitionExpression == null) {
                            commonPartitionExpression = statementPartitionExpression;
                            exampleSPstatement = stmt.getText();
                            exampleSPvalue = partitioning.getInferredPartitioningValue();
                        }
                        else if (commonPartitionExpression.equals(statementPartitionExpression) ||
                                   (statementPartitionExpression instanceof ParameterValueExpression &&
                                    commonPartitionExpression instanceof ParameterValueExpression)) {
                            // Any constant used for partitioning would have to be the same for all statements, but
                            // any statement parameter used for partitioning MIGHT come from the same proc parameter as
                            // any other statement's parameter used for partitioning.
                        }
                        else {
                            procWantsCommonPartitioning = false; // appears to be different partitioning for different statements
                        }
                    }
                    else {
                        // There is a statement with a partitioned table whose partitioning column is
                        // not equality filtered with a constant or param. Abandon all hope.
                        procWantsCommonPartitioning = false;
                    }

                // Usually, replicated-only statements in a mix with others have no effect on the MP/SP decision
                }
                else if (partitioning.getCountOfPartitionedTables() == 0) {
                    // but SP is strictly forbidden for DML, to maintain the consistency of the replicated data.
                    if (partitioning.getIsReplicatedTableDML()) {
                        procWantsCommonPartitioning = false;
                    }

                }
                else {
                    // There is a statement with a partitioned table whose partitioning column is
                    // not equality filtered with a constant or param. Abandon all hope.
                    procWantsCommonPartitioning = false;
                }
            }

            // if a single stmt is not read only, then the proc is not read only
            if (catalogStmt.getReadonly() == false) {
                procHasWriteStmts = true;
            }

            if (catalogStmt.getSeqscancount() > 0) {
                procHasSeqScans = true;
            }
        }

        // MIGHT the planner have uncovered an overlooked opportunity to run all statements SP?
        if (procWantsCommonPartitioning && (commonPartitionExpression != null)) {
            String msg = null;
            if (commonPartitionExpression instanceof ParameterValueExpression) {
                msg = "This procedure might benefit from an @ProcInfo annotation designating parameter " +
                        ((ParameterValueExpression) commonPartitionExpression).getParameterIndex() +
                        " of statement '" + exampleSPstatement + "'";
            } else {
                String valueDescription = null;
                if (exampleSPvalue == null) {
                    // Statements partitioned on a runtime constant. This is likely to be cryptic, but hopefully gets the idea across.
                    valueDescription = "of " + commonPartitionExpression.explain("");
                } else {
                    valueDescription = exampleSPvalue.toString(); // A simple constant value COULD have been a parameter.
                }
                msg = "This procedure might benefit from an @ProcInfo annotation referencing an added parameter passed the value " +
                        valueDescription;
            }
            compiler.addInfo(msg);
        }

        // set the read onlyness of a proc
        procedure.setReadonly(procHasWriteStmts == false);

        procedure.setHasseqscans(procHasSeqScans);

        for (Statement catalogStmt : procedure.getStatements()) {
            if (catalogStmt.getIscontentdeterministic() == false) {
                String potentialErrMsg =
                    "Procedure " + shortName + " has a statement with a non-deterministic result - statement: \"" +
                    catalogStmt.getSqltext() + "\" , reason: " + catalogStmt.getNondeterminismdetail();
                // throw compiler.new VoltCompilerException(potentialErrMsg);
                compiler.addWarn(potentialErrMsg);
            }
            else if (catalogStmt.getIsorderdeterministic() == false) {
                String warnMsg;
                if (procHasWriteStmts) {
                    String rwPotentialErrMsg = "Procedure " + shortName +
                            " is RW and has a statement whose result has a non-deterministic ordering - statement: \"" +
                            catalogStmt.getSqltext() + "\", reason: " + catalogStmt.getNondeterminismdetail();
                    // throw compiler.new VoltCompilerException(rwPotentialErrMsg);
                    warnMsg = rwPotentialErrMsg;
                }
                else {
                    warnMsg = "Procedure " + shortName +
                        " has a statement with a non-deterministic result - statement: \"" +
                        catalogStmt.getSqltext() + "\", reason: " + catalogStmt.getNondeterminismdetail();
                }
                compiler.addWarn(warnMsg);
            }
        }

        // set procedure parameter types
        CatalogMap<ProcParameter> params = procedure.getParameters();
        Class<?>[] paramTypes = lang.accept(procedureEntryPointParametersTypeExtractor, fields);
        for (int i = 0; i < paramTypes.length; i++) {
            Class<?> cls = paramTypes[i];
            ProcParameter param = params.add(String.valueOf(i));
            param.setIndex(i);

            // handle the case where the param is an array
            if (cls.isArray()) {
                param.setIsarray(true);
                cls = cls.getComponentType();
            }
            else
                param.setIsarray(false);

            // boxed types are not supported parameters at this time
            if ((cls == Long.class) || (cls == Integer.class) || (cls == Short.class) ||
                (cls == Byte.class) || (cls == Double.class) ||
                (cls == Character.class) || (cls == Boolean.class))
            {
                String msg = "Procedure: " + shortName + " has a parameter with a boxed type: ";
                msg += cls.getSimpleName();
                msg += ". Replace this parameter with the corresponding primitive type and the procedure may compile.";
                throw compiler.new VoltCompilerException(msg);
            } else if ((cls == Float.class) || (cls == float.class)) {
                String msg = "Procedure: " + shortName + " has a parameter with type: ";
                msg += cls.getSimpleName();
                msg += ". Replace this parameter type with double and the procedure may compile.";
                throw compiler.new VoltCompilerException(msg);

            }

            VoltType type;
            try {
                type = VoltType.typeFromClass(cls);
            }
            catch (VoltTypeException e) {
                // handle the case where the type is invalid
                String msg = "Procedure: " + shortName + " has a parameter with invalid type: ";
                msg += cls.getSimpleName();
                throw compiler.new VoltCompilerException(msg);
            }
            catch (RuntimeException e) {
                String msg = "Procedure: " + shortName + " unexpectedly failed a check on a parameter of type: ";
                msg += cls.getSimpleName();
                msg += " with error: ";
                msg += e.toString();
                throw compiler.new VoltCompilerException(msg);
            }

            param.setType(type.getValue());
        }

        // parse the procinfo
        procedure.setSinglepartition(info.singlePartition);
        if (info.singlePartition) {
            parsePartitionInfo(compiler, db, procedure, info.partitionInfo);
            if (procedure.getPartitionparameter() >= paramTypes.length) {
                String msg = "PartitionInfo parameter not a valid parameter for procedure: " + procedure.getClassname();
                throw compiler.new VoltCompilerException(msg);
            }

            // check the type of partition parameter meets our high standards
            Class<?> partitionType = paramTypes[procedure.getPartitionparameter()];
            Class<?>[] validPartitionClzzes = {
                    Long.class, Integer.class, Short.class, Byte.class,
                    long.class, int.class, short.class, byte.class,
                    String.class, byte[].class
            };
            boolean found = false;
            for (Class<?> candidate : validPartitionClzzes) {
                if (partitionType == candidate)
                    found = true;
            }
            if (!found) {
                String msg = "PartitionInfo parameter must be a String or Number for procedure: " + procedure.getClassname();
                throw compiler.new VoltCompilerException(msg);
            }

            VoltType columnType = VoltType.get((byte)procedure.getPartitioncolumn().getType());
            VoltType paramType = VoltType.typeFromClass(partitionType);
            if ( ! columnType.canExactlyRepresentAnyValueOf(paramType)) {
                String msg = "Type mismatch between partition column and partition parameter for procedure " +
                    procedure.getClassname() + " may cause overflow or loss of precision.\nPartition column is type " + columnType +
                    " and partition parameter is type " + paramType;
                throw compiler.new VoltCompilerException(msg);
            } else if ( ! paramType.canExactlyRepresentAnyValueOf(columnType)) {
                String msg = "Type mismatch between partition column and partition parameter for procedure " +
                        procedure.getClassname() + " does not allow the full range of partition key values.\nPartition column is type " + columnType +
                        " and partition parameter is type " + paramType;
                compiler.addWarn(msg);
View Full Code Here

Examples of org.voltdb.compiler.VoltCompiler.VoltCompilerException

            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 + " has a group " + 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);

        // get the annotation
        // first try to get one that has been passed from the compiler
        ProcInfoData info = compiler.getProcInfoOverride(shortName);
        // then check for the usual one in the class itself
        // 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.compile(compiler, hsql, catalog, 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
View Full Code Here

Examples of org.voltdb.compiler.VoltCompiler.VoltCompilerException

        assert(procedure.getSinglepartition() == true);

        // check this isn't empty
        if (info.length() == 0) {
            String msg = "Missing or Truncated PartitionInfo in attribute for procedure: " + procedure.getClassname();
            throw compiler.new VoltCompilerException(msg);
        }

        // split on the colon
        String[] parts = info.split(":");

        // if the colon doesn't split well, we have a problem
        if (parts.length != 2) {
            String msg = "Possibly invalid PartitionInfo in attribute for procedure: " + procedure.getClassname();
            throw compiler.new VoltCompilerException(msg);
        }

        // relabel the parts for code readability
        String columnInfo = parts[0].trim();
        int paramIndex = Integer.parseInt(parts[1].trim());

        int paramCount = procedure.getParameters().size();
        if ((paramIndex < 0) || (paramIndex >= paramCount)) {
            String msg = "PartitionInfo specifies invalid parameter index for procedure: " + procedure.getClassname();
            throw compiler.new VoltCompilerException(msg);
        }

        // locate the parameter
        procedure.setPartitionparameter(paramIndex);

        // split the columninfo
        parts = columnInfo.split("\\.");
        if (parts.length != 2) {
            String msg = "Possibly invalid PartitionInfo in attribute for procedure: " + procedure.getClassname();
            throw compiler.new VoltCompilerException(msg);
        }

        // relabel the parts for code readability
        String tableName = parts[0].trim();
        String columnName = parts[1].trim();

        // locate the partition column
        CatalogMap<Table> tables = db.getTables();
        for (Table table : tables) {
            if (table.getTypeName().equalsIgnoreCase(tableName)) {
                CatalogMap<Column> columns = table.getColumns();
                Column partitionColumn = table.getPartitioncolumn();
                if (partitionColumn == null) {
                    String msg = String.format("PartitionInfo for procedure %s references table %s which has no partition column (may be replicated).",
                            procedure.getClassname(), table.getTypeName());
                    throw compiler.new VoltCompilerException(msg);
                }

                for (Column column : columns) {
                    if (column.getTypeName().equalsIgnoreCase(columnName)) {
                        if (partitionColumn.getTypeName().equals(column.getTypeName())) {
                            procedure.setPartitioncolumn(column);
                            procedure.setPartitiontable(table);
                            return;
                        }
                        else {
                            String msg = "PartitionInfo for procedure " + procedure.getClassname() + " refers to a column in schema which is not a partition key.";
                            throw compiler.new VoltCompilerException(msg);
                        }
                    }
                }
            }
        }

        String msg = "PartitionInfo for procedure " + procedure.getClassname() + " refers to a column in schema which can't be found.";
        throw compiler.new VoltCompilerException(msg);
    }
View Full Code Here
TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.