Search in sources :

Example 1 with Function

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

the class CatalogSchemaTools method toSchema.

/**
     * Convert a catalog into a string containing all DDL statements.
     * @param catalog
     * @param importLines A set of importLines, should not be mutated.
     * @return String of DDL statements.
     */
public static String toSchema(Catalog catalog, Set<String> importLines) {
    StringBuilder sb = new StringBuilder();
    sb.append("-- This file was generated by VoltDB version ");
    sb.append(VoltDB.instance().getVersionString());
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
    String time = sdf.format(System.currentTimeMillis());
    sb.append(" on: " + time + ".\n");
    sb.append("-- This file represents the current database schema.\n");
    sb.append("-- Use this file as input to reproduce the current database structure in another database instance.\n");
    sb.append("--\n");
    sb.append(batchSpecificComments);
    sb.append("-- If the schema declares Java stored procedures, be sure to load the .jar file\n");
    sb.append("-- with the classes before loading the schema. For example:\n");
    sb.append("--\n");
    sb.append("-- LOAD CLASSES voltdb-procs.jar;\n");
    sb.append("-- FILE ddl.sql;\n");
    for (Cluster cluster : catalog.getClusters()) {
        for (Database db : cluster.getDatabases()) {
            toSchema(sb, importLines);
            for (Group grp : db.getGroups()) {
                toSchema(sb, grp);
            }
            sb.append("\n");
            List<Table> viewList = new ArrayList<>();
            CatalogMap<Table> tables = db.getTables();
            if (!tables.isEmpty()) {
                sb.append(startBatch);
                for (Table table : tables) {
                    Object annotation = table.getAnnotation();
                    if (annotation != null && ((TableAnnotation) annotation).ddl != null && table.getMaterializer() != null) {
                        viewList.add(table);
                        continue;
                    }
                    toSchema(sb, table, null, CatalogUtil.isTableExportOnly(db, table), (table.getPartitioncolumn() != null ? table.getPartitioncolumn().getName() : null), CatalogUtil.getExportTargetIfExportTableOrNullOtherwise(db, table));
                }
                // A View cannot precede a table that it depends on in the DDL
                for (Table table : viewList) {
                    String viewQuery = ((TableAnnotation) table.getAnnotation()).ddl;
                    toSchema(sb, table, viewQuery, false, null, null);
                }
            }
            CatalogMap<Procedure> procedures = db.getProcedures();
            if (!procedures.isEmpty()) {
                for (Procedure proc : procedures) {
                    toSchema(sb, proc);
                }
            }
            CatalogMap<Function> functions = db.getFunctions();
            if (!functions.isEmpty()) {
                for (Function func : functions) {
                    toSchema(sb, func);
                }
            }
            if (!tables.isEmpty()) {
                sb.append(endBatch);
            }
        }
    }
    if (dumpSchema) {
        String ts = new SimpleDateFormat("MMddHHmmssSSS").format(new Date());
        File f = new File(String.format("/tmp/canonical-%s.sql", ts));
        try {
            FileWriter fw = new FileWriter(f);
            fw.write(sb.toString());
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return sb.toString();
}
Also used : Group(org.voltdb.catalog.Group) Table(org.voltdb.catalog.Table) TableAnnotation(org.voltdb.compilereport.TableAnnotation) FileWriter(java.io.FileWriter) ArrayList(java.util.ArrayList) Cluster(org.voltdb.catalog.Cluster) IOException(java.io.IOException) Date(java.util.Date) Function(org.voltdb.catalog.Function) Database(org.voltdb.catalog.Database) Procedure(org.voltdb.catalog.Procedure) SimpleDateFormat(java.text.SimpleDateFormat) File(java.io.File)

Example 2 with Function

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

the class CreateFunctionFromMethod method processStatement.

@Override
protected boolean processStatement(DDLStatement ddlStatement, Database db, DdlProceduresToLoad whichProcs) throws VoltCompilerException {
    // Matches if it is CREATE FUNCTION <name> FROM METHOD <class-name>.<method-name>
    Matcher statementMatcher = SQLParser.matchCreateFunctionFromMethod(ddlStatement.statement);
    if (!statementMatcher.matches()) {
        return false;
    }
    // Before we complete the user-defined function feature, executing UDF-related DDLs will
    // generate compiler warnings.
    m_compiler.addWarn("User-defined functions are not implemented yet.");
    String functionName = checkIdentifierStart(statementMatcher.group(1), ddlStatement.statement).toLowerCase();
    String className = checkIdentifierStart(statementMatcher.group(2), ddlStatement.statement);
    String methodName = checkIdentifierStart(statementMatcher.group(3), ddlStatement.statement);
    CatalogMap<Function> functions = db.getFunctions();
    int functionId = FunctionForVoltDB.getFunctionId(functionName);
    if (functions.get(functionName) != null || FunctionSQL.isFunction(functionName) || FunctionCustom.getFunctionId(functionName) != ID_NOT_DEFINED || (functionId != ID_NOT_DEFINED && !FunctionForVoltDB.isUserDefinedFunctionId(functionId))) {
        throw m_compiler.new VoltCompilerException(String.format("Function \"%s\" is already defined.", functionName));
    }
    // Load class
    Class<?> funcClass;
    try {
        funcClass = Class.forName(className, true, m_classLoader);
    } catch (Throwable cause) {
        // wrap the error with a runtime exception that we can trap in our code.
        if (CoreUtils.isStoredProcThrowableFatalToServer(cause)) {
            throw (Error) cause;
        } else {
            throw m_compiler.new VoltCompilerException(String.format("Cannot load class for user-defined function: %s", className), cause);
        }
    }
    if (Modifier.isAbstract(funcClass.getModifiers())) {
        throw m_compiler.new VoltCompilerException(String.format("Cannot define a function using an abstract class %s", className));
    }
    // get the short name of the class (no package)
    String shortName = ProcedureCompiler.deriveShortProcedureName(className);
    // find the UDF method and get the params
    Method functionMethod = null;
    Method[] methods = funcClass.getDeclaredMethods();
    for (final Method m : methods) {
        String name = m.getName();
        if (name.equals(methodName)) {
            boolean found = true;
            StringBuilder warningMessage = new StringBuilder("Class " + shortName + " has a ");
            if (!Modifier.isPublic(m.getModifiers())) {
                warningMessage.append("non-public ");
                found = false;
            }
            if (Modifier.isStatic(m.getModifiers())) {
                warningMessage.append("static ");
                found = false;
            }
            if (m.getReturnType().equals(Void.TYPE)) {
                warningMessage.append("void ");
                found = false;
            }
            warningMessage.append(methodName);
            warningMessage.append("() method.");
            if (found) {
                // if not null, then we've got more than one run method
                if (functionMethod != null) {
                    String msg = "Class " + shortName + " has multiple methods named " + methodName;
                    msg += ". Only a single function method is supported.";
                    throw m_compiler.new VoltCompilerException(msg);
                }
                functionMethod = m;
            } else {
                m_compiler.addWarn(warningMessage.toString());
            }
        }
    }
    if (functionMethod == null) {
        String msg = "Cannot find the implementation method " + methodName + " for user-defined function " + functionName + " in class " + shortName;
        throw m_compiler.new VoltCompilerException(msg);
    }
    Class<?> returnTypeClass = functionMethod.getReturnType();
    if (!m_allowedDataTypes.contains(returnTypeClass)) {
        String msg = String.format("Method %s.%s has an unsupported return type %s", shortName, methodName, returnTypeClass.getName());
        throw m_compiler.new VoltCompilerException(msg);
    }
    Class<?>[] paramTypeClasses = functionMethod.getParameterTypes();
    for (int i = 0; i < paramTypeClasses.length; i++) {
        Class<?> paramType = paramTypeClasses[i];
        if (!m_allowedDataTypes.contains(paramType)) {
            String msg = String.format("Method %s.%s has an unsupported parameter type %s at position %d", shortName, methodName, paramType.getName(), i);
            throw m_compiler.new VoltCompilerException(msg);
        }
    }
    FunctionForVoltDB.registerUserDefinedFunction(functionName, returnTypeClass, paramTypeClasses);
    Function func = db.getFunctions().add(functionName);
    func.setFunctionname(functionName);
    func.setClassname(className);
    func.setMethodname(methodName);
    return true;
}
Also used : Matcher(java.util.regex.Matcher) Method(java.lang.reflect.Method) Function(org.voltdb.catalog.Function) VoltCompilerException(org.voltdb.compiler.VoltCompiler.VoltCompilerException)

Example 3 with Function

use of org.voltdb.catalog.Function 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

Function (org.voltdb.catalog.Function)3 Matcher (java.util.regex.Matcher)2 VoltCompilerException (org.voltdb.compiler.VoltCompiler.VoltCompilerException)2 File (java.io.File)1 FileWriter (java.io.FileWriter)1 IOException (java.io.IOException)1 Method (java.lang.reflect.Method)1 SimpleDateFormat (java.text.SimpleDateFormat)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 Cluster (org.voltdb.catalog.Cluster)1 Database (org.voltdb.catalog.Database)1 Group (org.voltdb.catalog.Group)1 Procedure (org.voltdb.catalog.Procedure)1 Table (org.voltdb.catalog.Table)1 TableAnnotation (org.voltdb.compilereport.TableAnnotation)1