Permalink
Browse files

Merge pull request #141 from VoltDB/ENG-3475

ENG-3475 Support for CREATE PROCEDURE FROM CLASS <class-name>, and PARTITION PROC...
  • Loading branch information...
2 parents 391083d + 5824c92 commit cd5de971db6057fb02c9515f46eb9a35dc14a663 @vtkstef vtkstef committed Aug 23, 2012
Oops, something went wrong.
@@ -0,0 +1,131 @@
+/* This file is part of VoltDB.
+ * Copyright (C) 2008-2012 VoltDB Inc.
+ *
+ * VoltDB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VoltDB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VoltDB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.voltdb.compiler;
+
+import static org.voltdb.compiler.ProcedureCompiler.deriveShortProcedureName;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.voltdb.compiler.VoltCompiler.ProcedureDescriptor;
+import org.voltdb.compiler.VoltCompiler.VoltCompilerException;
+
+/**
+ * Maintains and validates partition info.
+ * Maps between table names and partition column names,
+ * and procedures and their respective partition info
+ * Column name is null if replicated.
+ */
+public class PartitionMap {
+ final VoltCompiler m_compiler;
+ final Map<String, String> m_map = new HashMap<String, String>();
+ final Map<String, ProcedureDescriptor> m_procedureMap =
+ new HashMap<String, ProcedureDescriptor>();
+
+ /**
+ * Constructor needs a compiler instance to throw VoltCompilerException.
+ * @param compiler VoltCompiler instance
+ */
+ public PartitionMap(VoltCompiler compiler) {
+ m_compiler = compiler;
+ }
+
+ /**
+ * Add a table/column partition mapping for a PARTITION/REPLICATE statements.
+ * Validate input data and reject duplicates.
+ *
+ * @param tableName table name
+ * @param colName column name
+ * @throws VoltCompilerException
+ */
+ void put(String tableName, String colName) throws VoltCompilerException
+ {
+ // where is table and column validity checked?
+ if (tableName.length() == 0) {
+ throw m_compiler.new VoltCompilerException("PARTITION or REPLICATE has no TABLE specified");
+ }
+
+ if (m_map.containsKey(tableName.toLowerCase())) {
+ throw m_compiler.new VoltCompilerException(String.format(
+ "Partitioning already specified for table \"%s\"", tableName));
+ }
+
+ m_map.put(tableName.toLowerCase(), colName);
+ }
+
+ /**
+ * Tracks the given procedure descriptor if it is not already tracked
+ * @param descriptor a {@link VoltCompiler.ProcedureDescriptor}
+ * @throws VoltCompilerException if it is already tracked
+ */
+ void add(ProcedureDescriptor descriptor) throws VoltCompilerException
+ {
+ assert descriptor != null;
+
+ String className = descriptor.m_className;
+ 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);
+ }
+
+ /**
+ * Associates the given partition info to the given tracked procedure
+ * @param procedureName the short name of the procedure name
+ * @param partitionInfo the partition info to associate with the procedure
+ * @throws VoltCompilerException when there is no corresponding tracked
+ * procedure
+ */
+ void addProcedurePartitionInfoTo( String procedureName, String partitionInfo)
+ throws 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
+ descriptor = m_compiler.new ProcedureDescriptor(
+ descriptor.m_authGroups,
+ descriptor.m_className,
+ partitionInfo);
+
+ m_procedureMap.put(procedureName, descriptor);
+ }
+
+ /**
+ * gets the list of tracked procedure descriptors
+ * @return the list of tracked procedure descriptors
+ */
+ Collection<ProcedureDescriptor> getProcedureDescriptors() {
+ return m_procedureMap.values();
+ }
+
+}
@@ -119,6 +119,21 @@ static void compile(VoltCompiler compiler, HSQLInterface hsql,
return retval;
}
+ /**
+ * get the short name of the class (no package)
+ * @param className fully qualified (or not) class name
+ * @return short name of the class (no package)
+ */
+ static String deriveShortProcedureName( String className) {
+ if( className == null || className.trim().isEmpty()) {
+ return null;
+ }
+ String[] parts = className.split("\\.");
+ String shortName = parts[parts.length - 1];
+
+ return shortName;
+ }
+
static void compileJavaProcedure(VoltCompiler compiler, HSQLInterface hsql,
DatabaseEstimates estimates, Catalog catalog, Database db,
@@ -137,8 +152,7 @@ static void compileJavaProcedure(VoltCompiler compiler, HSQLInterface hsql,
}
// get the short name of the class (no package)
- String[] parts = className.split("\\.");
- String shortName = parts[parts.length - 1];
+ String shortName = deriveShortProcedureName(className);
// add an entry to the catalog
final Procedure procedure = db.getProcedures().add(shortName);
@@ -159,15 +173,31 @@ static void compileJavaProcedure(VoltCompiler compiler, HSQLInterface hsql,
// 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 && 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);
+ }
if (annotationInfo != null) {
info.partitionInfo = annotationInfo.partitionInfo();
info.singlePartition = annotationInfo.singlePartition();
}
+ else if (ddlInfo != null) {
+ info = ddlInfo;
+ }
}
assert(info != null);
@@ -1,64 +0,0 @@
-/* This file is part of VoltDB.
- * Copyright (C) 2008-2012 VoltDB Inc.
- *
- * VoltDB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VoltDB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VoltDB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.voltdb.compiler;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.voltdb.compiler.VoltCompiler.VoltCompilerException;
-
-/**
- * Maintains and validates table partition info.
- * Maps between table names and partition column names.
- * Column name is null if replicated.
- */
-public class TablePartitionMap {
- final VoltCompiler m_compiler;
- final Map<String, String> m_map = new HashMap<String, String>();
-
- /**
- * Constructor needs a compiler instance to throw VoltCompilerException.
- * @param compiler VoltCompiler instance
- */
- public TablePartitionMap(VoltCompiler compiler) {
- m_compiler = compiler;
- }
-
- /**
- * Add a table/column partition mapping for a PARTITION/REPLICATE statements.
- * Validate input data and reject duplicates.
- *
- * @param tableName table name
- * @param colName column name
- * @throws VoltCompilerException
- */
- void put(String tableName, String colName) throws VoltCompilerException
- {
- // where is table and column validity checked?
- if (tableName.length() == 0) {
- throw m_compiler.new VoltCompilerException("PARTITION or REPLICATE has no TABLE specified");
- }
-
- if (m_map.containsKey(tableName.toLowerCase())) {
- throw m_compiler.new VoltCompilerException(String.format(
- "Partitioning already specified for table \"%s\"", tableName));
- }
-
- m_map.put(tableName.toLowerCase(), colName);
- }
-}
@@ -246,6 +246,18 @@ public void warning(final SAXParseException exception) throws SAXException {
m_builtInStmt = false;
}
+ ProcedureDescriptor (final ArrayList<String> authGroups, final String className, String partitionString) {
+ assert(className != null);
+ assert(partitionString != null);
+
+ m_authGroups = authGroups;
+ m_className = className;
+ m_singleStmt = null;
+ m_joinOrder = null;
+ m_partitionString = partitionString;
+ m_builtInStmt = false;
+ }
+
ProcedureDescriptor (final ArrayList<String> authGroups, final String className,
final String singleStmt, final String joinOrder, final String partitionString,
boolean builtInStmt)
@@ -497,7 +509,7 @@ void compileDatabaseNode(DatabaseType database) throws VoltCompilerException {
final ArrayList<String> schemas = new ArrayList<String>();
final ArrayList<ProcedureDescriptor> procedures = new ArrayList<ProcedureDescriptor>();
final ArrayList<Class<?>> classDependencies = new ArrayList<Class<?>>();
- final TablePartitionMap partitionMap = new TablePartitionMap(this);
+ final PartitionMap partitionMap = new PartitionMap(this);
final String databaseName = database.getName();
@@ -532,7 +544,7 @@ void compileDatabaseNode(DatabaseType database) throws VoltCompilerException {
// procedures/procedure
if (database.getProcedures() != null) {
for (ProceduresType.Procedure proc : database.getProcedures().getProcedure()) {
- procedures.add(getProcedure(proc));
+ partitionMap.add(getProcedure(proc));
}
}
@@ -671,6 +683,9 @@ void compileDatabaseNode(DatabaseType database) throws VoltCompilerException {
List<ProcedureDescriptor> autoCrudProcedures = generateCrud(m_catalog);
procedures.addAll(autoCrudProcedures);
+ // Add procedures read from DDL and project file
+ procedures.addAll( partitionMap.getProcedureDescriptors());
+
// Actually parse and handle all the Procedures
for (final ProcedureDescriptor procedureDescriptor : procedures) {
final String procedureName = procedureDescriptor.m_className;
Oops, something went wrong.

0 comments on commit cd5de97

Please sign in to comment.