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();
}
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;
}
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;
}
Aggregations