Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
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...
commit cd5de971db6057fb02c9515f46eb9a35dc14a663 2 parents 391083d + 5824c92
@vtkstef vtkstef authored
View
380 src/frontend/org/voltdb/compiler/DDLCompiler.java
@@ -27,9 +27,9 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
import org.hsqldb_voltpatches.HSQLInterface;
import org.hsqldb_voltpatches.HSQLInterface.HSQLParseException;
import org.hsqldb_voltpatches.VoltXMLElement;
@@ -42,6 +42,7 @@
import org.voltdb.catalog.Index;
import org.voltdb.catalog.MaterializedViewInfo;
import org.voltdb.catalog.Table;
+import org.voltdb.compiler.VoltCompiler.ProcedureDescriptor;
import org.voltdb.compiler.VoltCompiler.VoltCompilerException;
import org.voltdb.expressions.AbstractExpression;
import org.voltdb.expressions.TupleValueExpression;
@@ -55,6 +56,7 @@
import org.voltdb.utils.Encoder;
import org.voltdb.utils.VoltTypeUtil;
+
/**
* Compiles schema (SQL DDL) text files and stores the results in a given catalog.
*
@@ -64,13 +66,183 @@
static final int MAX_COLUMNS = 1024;
static final int MAX_ROW_SIZE = 1024 * 1024 * 2;
+ /**
+ * Regex Description:
+ * <pre>
+ * (?i) -- ignore case
+ * \\A -- beginning of statement
+ * PARTITION -- token
+ * \\s+ one or more spaces
+ * (PROCEDURE|TABLE) -- either PROCEDURE or TABLE token
+ * \\s+ -- one or more spaces
+ * .+ -- one or more of any characters
+ * ; -- a semicolon
+ * \\z -- end of string
+ * </pre>
+ */
+ static final Pattern prePartitionPattern = Pattern.compile(
+ "(?i)\\APARTITION\\s+(PROCEDURE|TABLE)\\s+.+;\\z"
+ );
+ /**
+ * NB supports only unquoted table and column names
+ *
+ * Regex Description:
+ * <pre>
+ * (?i) -- ignore case
+ * \\A -- beginning of statement
+ * PARTITION -- token
+ * \\s+ -- one or more spaces
+ * TABLE -- token
+ * \\s+ -- one or more spaces
+ * ([\\w$]+) -- [table name capture group 1]
+ * [\\w$]+ -- 1 or more identifier character
+ * (letters, numbers, dollar sign ($) underscore (_))
+ * \\s+ -- one or more spaces
+ * ON -- token
+ * \\s+ -- one or more spaces
+ * COLUMN -- token
+ * \\s+ -- one or more spaces
+ * ([\\w$]+) -- [column name capture group 2]
+ * [\\w$]+ -- 1 or more identifier character
+ * (letters, numbers, dollar sign ($) or underscore (_))
+ * \\s* -- 0 or more spaces
+ * ; a -- semicolon
+ * \\z -- end of string
+ * </pre>
+ */
+ static final Pattern partitionTablePattern = Pattern.compile(
+ "(?i)\\APARTITION\\s+TABLE\\s+([\\w$]+)\\s+ON\\s+COLUMN\\s+([\\w$]+)\\s*;\\z"
+ );
+ /**
+ * NB supports only unquoted table and column names
+ *
+ * Regex Description:
+ * <pre>
+ * (?i) -- ignore case
+ * \\A -- beginning of statement
+ * PARTITION -- token
+ * \\s+ -- one or more spaces
+ * PROCEDURE -- token
+ * \\s+ -- one or more spaces
+ * ([\\w$]+) -- [procedure name capture group 1]
+ * [\\w$]+ -- one or more identifier character
+ * (letters, numbers, dollar sign ($) or underscore (_))
+ * \\s+ -- one or more spaces
+ * ON -- token
+ * \\s+ -- one or more spaces
+ * ' -- single quote
+ * \\s* -- 0 or more spaces
+ * (([\\w$]+)\\.([\\w$]+)\\s*:\\s*(\\d+)) -- [partition info capture group 2]
+ * ([\\w$]+) -- [table name capture group 3]
+ * [\\w$]+ -- one or more identifier character
+ * (letters, numbers, dollar sign ($) or underscore (_))
+ * \\. -- a period
+ * ([\\w$]+) -- [column name capture group 4]
+ * [\\w$]+ -- one or more identifier character
+ * (letters, numbers, dollar sign ($) or underscore (_))
+ * \\s* -- 0 or more spaces
+ * : column
+ * \\s* -- 0 or more spaces
+ * \\d+ -- one ore more number digits [parameter index capture group 5]
+ * \\s* -- 0 or more spaces
+ * ' -- single quote
+ * \\s* -- 0 or more spaces
+ * ; -- a semicolon
+ * \\z -- end of string
+ * </pre>
+ */
+ static final Pattern partitionProcedurePattern = Pattern.compile(
+ "(?i)\\APARTITION\\s+PROCEDURE\\s+([\\w$]+)\\s+ON\\s+" +
+ "'\\s*(([\\w$]+)\\.([\\w$]+)\\s*:\\s*(\\d+))\\s*'\\s*;\\z"
+ );
+ /**
+ * NB supports only unquoted table and column names
+ *
+ * Regex Description:
+ * <pre>
+ * (?i) -- ignore case
+ * \\A -- beginning of statement
+ * CREATE -- token
+ * \\s+ -- one or more spaces
+ * PROCEDURE -- token
+ * \\s+ -- one or more spaces
+ * FROM -- token
+ * \\s+ -- one or more spaces
+ * CLASS -- token
+ * \\s+ -- one or more spaces
+ * ([\\w$.]+) -- [class name capture group 1]
+ * [\\w$]+ -- one or more identifier character
+ * (letters, numbers, dollar sign ($), underscore (_) or period (.))
+ * \\s* -- 0 or more spaces
+ * ; -- a semicolon
+ * \\z -- end of string
+ * </pre>
+ */
+ static final Pattern procedureClassPattern = Pattern.compile(
+ "(?i)\\ACREATE\\s+PROCEDURE\\s+FROM\\s+CLASS\\s+([\\w$.]+)\\s*;\\z"
+ );
+ /**
+ * NB supports only unquoted table and column names
+ *
+ * Regex Description:
+ * <pre>
+ * (?i) -- ignore case
+ * \\A -- beginning of statement
+ * REPLICATE -- token
+ * \\s+ -- one or more spaces
+ * TABLE -- token
+ * \\s+ -- one or more spaces
+ * ([\\w$.]+) -- [table name capture group 1]
+ * [\\w$]+ -- one or more identifier character (letters, numbers, dollar sign ($) or underscore (_))
+ * \\s* -- 0 or more spaces
+ * ; -- a semicolon
+ * \\z -- end of string
+ * </pre>
+ */
+ static final Pattern replicatePattern = Pattern.compile(
+ "(?i)\\AREPLICATE\\s+TABLE\\s+([\\w$]+)\\s*;\\z"
+ );
+ /**
+ * Regex Description:
+ *
+ * if the statement starts with either create procedure, partition, or
+ * replicate the first match group is set to respectively procedure,
+ * partition, or replicate
+ * <pre>
+ * (?i) -- ignore case
+ * ((?<=\\ACREATE\\s{0,1024})PROCEDURE|\\APARTITION|\\AREPLICATE) -- voltdb ddl
+ * [capture group 1]
+ * (?<=\\ACREATE\\s{1,1024})PROCEDURE -- create procedure ddl
+ * (?<=\\ACREATE\\s{0,1024}) -- CREATE zero-width positive lookbehind
+ * \\A -- beginning of statement
+ * CREATE -- token
+ * \\s{1,1024} -- one or up to 1024 spaces
+ * PROCEDURE -- procedure token
+ * | -- or
+ * \\A -- beginning of statement
+ * -- PARTITION token
+ * | -- or
+ * \\A -- beginning of statement
+ * REPLICATE -- token
+ * \\s -- one space
+ * </pre>
+ */
+ static final Pattern voltdbStatementPrefixPattern = Pattern.compile(
+ "(?i)((?<=\\ACREATE\\s{0,1024})PROCEDURE|\\APARTITION|\\AREPLICATE)\\s"
+ );
+
+ static final String TABLE = "TABLE";
+ static final String PROCEDURE = "PROCEDURE";
+ static final String PARTITION = "PARTITION";
+ static final String REPLICATE = "REPLICATE";
+
HSQLInterface m_hsql;
VoltCompiler m_compiler;
String m_fullDDL = "";
int m_currLineNo = 1;
/// Partition descriptors parsed from DDL PARTITION or REPLICATE statements.
- final TablePartitionMap m_partitionMap;
+ final PartitionMap m_partitionMap;
HashMap<String, Column> columnMap = new HashMap<String, Column>();
HashMap<String, Index> indexMap = new HashMap<String, Index>();
@@ -83,13 +255,14 @@ public DDLStatement() {
int lineNo;
}
- public DDLCompiler(VoltCompiler compiler, HSQLInterface hsql, TablePartitionMap partitionMap) {
+ public DDLCompiler(VoltCompiler compiler, HSQLInterface hsql, PartitionMap partitionMap) {
assert(compiler != null);
assert(hsql != null);
assert(partitionMap != null);
this.m_hsql = hsql;
this.m_compiler = compiler;
this.m_partitionMap = partitionMap;
+
}
/**
@@ -119,6 +292,7 @@ public void loadSchema(String path)
*/
public void loadSchema(String path, FileReader reader)
throws VoltCompiler.VoltCompilerException {
+
DDLStatement stmt = getNextStatement(reader, m_compiler);
while (stmt != null) {
// Some statements are processed by VoltDB and the rest are handled by HSQL.
@@ -153,83 +327,169 @@ public void loadSchema(String path, FileReader reader)
}
/**
- * Process a VoltDB-specific DDL statement, like PARTITION and REPLICATE.
+ * Checks whether or not the start of the given identifier is java (and
+ * thus DDL) compliant. An identifier may start with: _ [a-zA-Z] $
+ * @param identifier the identifier to check
+ * @param statement the statement where the identifier is
+ * @return the given identifier unmodified
+ * @throws VoltCompilerException when it is not compliant
+ */
+ private String checkIdentifierStart(
+ final String identifier, final String statement
+ ) throws VoltCompilerException {
+
+ assert identifier != null && ! identifier.trim().isEmpty();
+ assert statement != null && ! statement.trim().isEmpty();
+
+ int loc = 0;
+ do {
+ if( ! Character.isJavaIdentifierStart(identifier.charAt(loc))) {
+ String msg = "Bad indentifier in DDL: \"" +
+ statement.substring(0,statement.length()-1) +
+ "\" contains invalid identifier \"" + identifier + "\"";
+ throw m_compiler.new VoltCompilerException(msg);
+ }
+ loc = identifier.indexOf('.', loc) + 1;
+ }
+ while( loc > 0 && loc < identifier.length());
+
+ return identifier;
+ }
+
+ /**
+ * Process a VoltDB-specific DDL statement, like PARTITION, REPLICATE, and
+ * CREATE PROCEDURE
* @param statement DDL statement string
* @return true if statement was handled, otherwise it should be passed to HSQL
* @throws VoltCompilerException
*/
private boolean processVoltDBStatement(String statement) throws VoltCompilerException {
- if (statement == null) {
+ if (statement == null || statement.trim().isEmpty()) {
return false;
}
- // Split the statement on whitespace. For now the supported statements
- // don't have quoted strings or anything else more than simple tokens.
- String[] tokens = statement.trim().split("\\s+");
- if (tokens.length == 0) {
+ statement = statement.trim();
+
+ // matches if it is the beginning of a voltDB statement
+ Matcher statementMatcher = voltdbStatementPrefixPattern.matcher(statement);;
+ if( ! statementMatcher.find()) {
return false;
}
- // Handle PARTITION statement.
- if (tokens[0].equalsIgnoreCase("PARTITION")) {
- // Check and strip semi-colon terminator.
- tokens = cleanupVoltDBDDLTerminator("PARTITION", tokens);
- // Validate tokens.
- if ( tokens.length != 6
- || !tokens[1].equalsIgnoreCase("table")
- || !tokens[3].equalsIgnoreCase("on")
- || !tokens[4].equalsIgnoreCase("column")) {
- throw m_compiler.new VoltCompilerException(String.format(
- "Bad PARTITION DDL statement: \"%s\", " +
- "expected syntax: PARTITION TABLE <table> ON COLUMN <column>",
- StringUtils.join(tokens, ' ')));
- }
- m_partitionMap.put(tokens[2], tokens[5]);
+ // either PROCEDURE, REPLICATE, or PARTITION
+ String commandPrefix = statementMatcher.group(1).toUpperCase();
+
+ // matches if it is CREATE PROCEDURE FROM CLASS <class-name>;
+ statementMatcher = procedureClassPattern.matcher(statement);
+ if( statementMatcher.matches()) {
+ String clazz = checkIdentifierStart(statementMatcher.group(1), statement);
+
+ ProcedureDescriptor descriptor = m_compiler.new ProcedureDescriptor(
+ new ArrayList<String>(), clazz);
+
+ // track the defined procedure
+ m_partitionMap.add(descriptor);
return true;
}
- // Handle REPLICATE statement.
- else if (tokens[0].equalsIgnoreCase("REPLICATE")) {
- // Check and strip semi-colon terminator.
- tokens = cleanupVoltDBDDLTerminator("REPLICATE", tokens);
- // Validate tokens.
- if ( tokens.length != 3
- || !tokens[1].equalsIgnoreCase("table")) {
- throw m_compiler.new VoltCompilerException(String.format(
- "Bad REPLICATE DDL statement: \"%s\", " +
- "expected syntax: REPLICATE TABLE <table>",
- StringUtils.join(tokens, ' ')));
+ // matches if it is the beginning of a partition statement
+ statementMatcher = prePartitionPattern.matcher(statement);
+ if( statementMatcher.matches()) {
+
+ // either TABLE or PROCEDURE
+ String partitionee = statementMatcher.group(1).toUpperCase();
+ if( TABLE.equals(partitionee)) {
+
+ // matches if it is PARTITION TABLE <table> ON COLUMN <column>
+ statementMatcher = partitionTablePattern.matcher(statement);
+
+ if( ! statementMatcher.matches()) {
+ throw m_compiler.new VoltCompilerException(String.format(
+ "Bad PARTITION DDL statement: \"%s\", " +
+ "expected syntax: PARTITION TABLE <table> ON COLUMN <column>",
+ statement.substring(0,statement.length()-1))); // remove trailing semicolon
+ }
+ // group(1) -> table, group(2) -> column
+ m_partitionMap.put(
+ checkIdentifierStart(statementMatcher.group(1),statement),
+ checkIdentifierStart(statementMatcher.group(2),statement)
+ );
+ return true;
+ }
+ else if( PROCEDURE.equals(partitionee)) {
+
+ // matches if it is
+ // PARTITION PROCEDURE <procedure>
+ // ON '<table>.<column>: <parameter-index-no>'
+ statementMatcher = partitionProcedurePattern.matcher(statement);
+
+ if( ! statementMatcher.matches()) {
+ throw m_compiler.new VoltCompilerException(String.format(
+ "Bad PARTITION DDL statement: \"%s\", " +
+ "expected syntax: PARTITION PROCEDURE <procedure> ON "+
+ "'<table>.<column>: <parameter-index-no>'",
+ statement.substring(0,statement.length()-1))); // remove trailing semicolon
+ }
+
+ // check the table portion of the partition info
+ checkIdentifierStart(statementMatcher.group(3), statement);
+
+ // check the column portion of the partition info
+ checkIdentifierStart(statementMatcher.group(4), statement);
+
+ // procedureName -> group(1), partitionInfo -> group(2)
+ m_partitionMap.addProcedurePartitionInfoTo(
+ checkIdentifierStart(statementMatcher.group(1), statement),
+ statementMatcher.group(2)
+ );
+
+ return true;
}
- m_partitionMap.put(tokens[2], null);
+ // can't get here as regex only matches for PROCEDURE or TABLE
+ }
+
+ // matches if it is REPLICATE TABLE <table-name>
+ statementMatcher = replicatePattern.matcher(statement);
+ if( statementMatcher.matches()) {
+ // group(1) -> table
+ m_partitionMap.put(
+ checkIdentifierStart(statementMatcher.group(1), statement),
+ null
+ );
return true;
}
- // Not a VoltDB-specific DDL statement.
- return false;
- }
+ /*
+ * if no correct syntax regex matched above then at this juncture
+ * the statement is syntax incorrect
+ */
- /**
- * Strip trailing semi-colon, either as it's own token or at the end
- * of the last token. Throw exception if there is no semi-colon.
- * @param tokens
- * @return processed tokens
- * @throws VoltCompilerException
- */
- private String[] cleanupVoltDBDDLTerminator(final String statementName, final String[] tokens)
- throws VoltCompilerException {
- assert(tokens.length > 0);
- String[] startTokens = ArrayUtils.subarray(tokens, 0, tokens.length-1);
- String endToken = tokens[tokens.length-1];
- if (!endToken.endsWith(";")) {
+ if( PARTITION.equals(commandPrefix)) {
throw m_compiler.new VoltCompilerException(String.format(
- "%s DDL statement is not terminated by a semi-colon: \"%s\".",
- StringUtils.join(tokens, ' ')));
+ "Bad PARTITION DDL statement: \"%s\", " +
+ "expected syntax: \"PARTITION TABLE <table> ON COLUMN <column>\" or " +
+ "\"PARTITION PROCEDURE <procedure> ON " +
+ "'<table>.<column>: <parameter-index-no>'\"",
+ statement.substring(0,statement.length()-1))); // remove trailing semicolon
}
- if (endToken.equals(";")) {
- return startTokens;
+
+ if( REPLICATE.equals(commandPrefix)) {
+ throw m_compiler.new VoltCompilerException(String.format(
+ "Bad REPLICATE DDL statement: \"%s\", " +
+ "expected syntax: REPLICATE TABLE <table>",
+ statement.substring(0,statement.length()-1))); // remove trailing semicolon
+ }
+
+ if( PROCEDURE.equals(commandPrefix)) {
+ throw m_compiler.new VoltCompilerException(String.format(
+ "Bad CREATE PROCEDURE DDL statement: \"%s\", " +
+ "expected syntax: \"CREATE PROCEDURE FROM CLASS <class-name>\"",
+ statement.substring(0,statement.length()-1))); // remove trailing semicolon
}
- return ArrayUtils.add(startTokens, endToken.substring(0, endToken.length()-1));
+
+ // Not a VoltDB-specific DDL statement.
+ return false;
}
public void compileToCatalog(Catalog catalog, Database db) throws VoltCompilerException {
@@ -684,7 +944,7 @@ else if (indexNameNoCase.contains("hash"))
else
{
String msg = "Index " + name + " in table " + table.getTypeName() +
- " uses a non-hashable column" + nonint_col_name;
+ " uses a non-hashable column" + nonint_col_name;
throw m_compiler.new VoltCompilerException(msg);
}
} else {
@@ -708,7 +968,7 @@ else if (indexNameNoCase.contains("hash"))
index.setUnique(unique);
String msg = "Created index: " + name + " on table: " +
- table.getTypeName() + " of type: " + IndexType.get(index.getType()).name();
+ table.getTypeName() + " of type: " + IndexType.get(index.getType()).name();
m_compiler.addInfo(msg);
View
131 src/frontend/org/voltdb/compiler/PartitionMap.java
@@ -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();
+ }
+
+}
View
34 src/frontend/org/voltdb/compiler/ProcedureCompiler.java
@@ -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);
View
64 src/frontend/org/voltdb/compiler/TablePartitionMap.java
@@ -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);
- }
-}
View
19 src/frontend/org/voltdb/compiler/VoltCompiler.java
@@ -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;
View
50 tests/frontend/org/voltdb/compiler/TestPartitionDDL.java
@@ -154,10 +154,10 @@ String writeXML(final boolean partitioned, final String ddlPath, final Item... i
}
xmlText += " <procedures>\n";
xmlText += String.format(" <procedure class='%s' />\n",
- partitioned ? partitionedProc : replicatedProc);
+ partitioned ? partitionedProc : replicatedProc);
xmlText += " </procedures>\n" +
- " </database>\n" +
- "</project>\n";
+ " </database>\n" +
+ "</project>\n";
return VoltProjectBuilder.writeStringToTempFile(xmlText).getPath();
}
@@ -174,7 +174,7 @@ String getMessages(final VoltCompiler compiler, final boolean success) {
return ss.toString().trim().replace('\n', ' ');
}
- // Must provide a failRegex if failure is expected.
+ // Must provide a failRegex if failure is expected.
void test(final boolean partitioned, final String failRegex, final Item... items) {
// Generate DDL and XML files.
String ddlPath = writeDDL(items);
@@ -189,7 +189,7 @@ void test(final boolean partitioned, final String failRegex, final Item... items
if (failRegex != null) {
assertFalse("Expected compilation failure.", success);
assertTrue(String.format("Expected error regex \"%s\" not matched.\n%s", failRegex, s),
- s.matches(failRegex));
+ s.matches(failRegex));
}
else {
assertTrue(String.format("Unexpected compilation failure.\n%s", s), success);
@@ -252,19 +252,23 @@ public void testBadReplicate() {
// REPLICATE statement with no semi-colon.
tester.bad(".*no semicolon found.*",
- new DDL("REPLICATE TABLE books"));
+ new DDL("REPLICATE TABLE books"));
// REPLICATE statement with missing argument.
tester.bad(".*Bad REPLICATE DDL statement.*",
- new DDL("REPLICATE TABLE;"));
+ new DDL("REPLICATE TABLE;"));
// REPLICATE statement with too many arguments.
tester.bad(".*Bad REPLICATE DDL statement.*",
- new DDL("REPLICATE TABLE books NOW;"));
+ new DDL("REPLICATE TABLE books NOW;"));
// REPLICATE with bad table clause.
tester.bad(".*Bad REPLICATE DDL statement.*",
- new DDL("REPLICATE TABLEX books;"));
+ new DDL("REPLICATE TABLEX books;"));
+
+ //REPLICATE with bad table identifier
+ tester.bad(".*Bad indentifier in DDL.*",
+ new DDL("REPLICATE TABLE 0books;"));
}
public void testGoodReplicate() {
@@ -282,19 +286,23 @@ public void testBadPartition() {
// PARTITION statement with no semi-colon.
tester.bad(".*no semicolon found.*",
- new DDL("PARTITION TABLE books ON COLUMN cash"));
+ new DDL("PARTITION TABLE books ON COLUMN cash"));
// PARTITION statement with missing arguments.
tester.bad(".*Bad PARTITION DDL statement.*",
- new DDL("PARTITION TABLE;"));
+ new DDL("PARTITION TABLE;"));
// PARTITION statement with too many arguments.
tester.bad(".*Bad PARTITION DDL statement.*",
- new DDL("PARTITION TABLE books ON COLUMN cash COW;"));
+ new DDL("PARTITION TABLE books ON COLUMN cash COW;"));
+
+ // PARTITION statement intermixed with procedure.
+ tester.bad(".*Bad PARTITION DDL statement.*",
+ new DDL("PARTITION TABLE books PROCEDURE bruha ON COLUMN cash;"));
// PARTITION with bad table clause.
tester.bad(".*Bad PARTITION DDL statement.*",
- new DDL("PARTITION TABLEX books ON COLUMN cash;"));
+ new DDL("PARTITION TABLEX books ON COLUMN cash;"));
}
public void testGoodPartition() {
@@ -315,22 +323,22 @@ public void testRedundant() {
// PARTITION from both XML and DDL.
tester.bad(".*Partitioning already specified for table.*",
- new PartitionXML("books", "cash"),
- new PartitionDDL("books", "cash"));
+ new PartitionXML("books", "cash"),
+ new PartitionDDL("books", "cash"));
// PARTITION and REPLICATE from both XML and DDL.
tester.bad(".*Partitioning already specified for table.*",
- new PartitionXML("books", "cash"),
- new ReplicateDDL("books"));
+ new PartitionXML("books", "cash"),
+ new ReplicateDDL("books"));
// PARTITION and REPLICATE from DDL.
tester.bad(".*Partitioning already specified for table.*",
- new PartitionDDL("books", "cash"),
- new ReplicateDDL("books"));
+ new PartitionDDL("books", "cash"),
+ new ReplicateDDL("books"));
// PARTITION twice from DDL.
tester.bad(".*Partitioning already specified for table.*",
- new PartitionDDL("books", "cash"),
- new PartitionDDL("books", "cash"));
+ new PartitionDDL("books", "cash"),
+ new PartitionDDL("books", "cash"));
}
}
View
580 tests/frontend/org/voltdb/compiler/TestVoltCompiler.java
@@ -74,12 +74,12 @@ public void testBrokenLineParsing() throws IOException {
"create table table1r_el (pkey integer, column2_integer integer, PRIMARY KEY(pkey));\n" +
"create view v_table1r_el (column2_integer, num_rows) as\n" +
"select column2_integer as column2_integer,\n" +
- "count(*) as num_rows\n" +
+ "count(*) as num_rows\n" +
"from table1r_el\n" +
"group by column2_integer;\n" +
"create view v_table1r_el2 (column2_integer, num_rows) as\n" +
"select column2_integer as column2_integer,\n" +
- "count(*) as num_rows\n" +
+ "count(*) as num_rows\n" +
"from table1r_el\n" +
"group by column2_integer\n;\n";
@@ -137,16 +137,37 @@ public void testMismatchedPartitionParams() throws IOException {
fbs = checkPartitionParam("CREATE TABLE PKEY_BIGINT ( PKEY BIGINT NOT NULL, PRIMARY KEY (PKEY) );" +
- "PARTITION TABLE PKEY_BIGINT ON COLUMN PKEY;",
- "org.voltdb.compiler.procedures.PartitionParamBigint", "PKEY_BIGINT");
+ "PARTITION TABLE PKEY_BIGINT ON COLUMN PKEY;",
+ "org.voltdb.compiler.procedures.PartitionParamBigint", "PKEY_BIGINT");
expectedError =
"Type mismatch between partition column and partition parameter for procedure " +
"org.voltdb.compiler.procedures.PartitionParamBigint may cause overflow or loss of precision.\n" +
"Partition column is type VoltType.BIGINT and partition parameter is type VoltType.STRING";
assertTrue(isFeedbackPresent(expectedError, fbs));
+ fbs = checkPartitionParam("CREATE TABLE PKEY_BIGINT ( PKEY BIGINT NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_BIGINT ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.PartitionParamBigint;",
+ "PKEY_BIGINT");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.PartitionParamBigint may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.BIGINT and partition parameter is type VoltType.STRING";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkPartitionParam("CREATE TABLE PKEY_BIGINT ( PKEY BIGINT NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_BIGINT ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamBigint;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamBigint ON 'PKEY_BIGINT.PKEY: 0';",
+ "PKEY_BIGINT");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.NotAnnotatedPartitionParamBigint may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.BIGINT and partition parameter is type VoltType.STRING";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
fbs = checkPartitionParam("CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
- "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;",
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;",
"org.voltdb.compiler.procedures.PartitionParamInteger",
"PKEY_INTEGER");
expectedError =
@@ -156,8 +177,31 @@ public void testMismatchedPartitionParams() throws IOException {
"is type VoltType.BIGINT";
assertTrue(isFeedbackPresent(expectedError, fbs));
+ fbs = checkPartitionParam("CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.PartitionParamInteger;",
+ "PKEY_INTEGER");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.PartitionParamInteger may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.INTEGER and partition parameter " +
+ "is type VoltType.BIGINT";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkPartitionParam("CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';",
+ "PKEY_INTEGER");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.INTEGER and partition parameter " +
+ "is type VoltType.BIGINT";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
fbs = checkPartitionParam("CREATE TABLE PKEY_SMALLINT ( PKEY SMALLINT NOT NULL, PRIMARY KEY (PKEY) );" +
- "PARTITION TABLE PKEY_SMALLINT ON COLUMN PKEY;",
+ "PARTITION TABLE PKEY_SMALLINT ON COLUMN PKEY;",
"org.voltdb.compiler.procedures.PartitionParamSmallint",
"PKEY_SMALLINT");
expectedError =
@@ -167,8 +211,31 @@ public void testMismatchedPartitionParams() throws IOException {
"is type VoltType.BIGINT";
assertTrue(isFeedbackPresent(expectedError, fbs));
+ fbs = checkPartitionParam("CREATE TABLE PKEY_SMALLINT ( PKEY SMALLINT NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_SMALLINT ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.PartitionParamSmallint;",
+ "PKEY_SMALLINT");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.PartitionParamSmallint may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.SMALLINT and partition parameter " +
+ "is type VoltType.BIGINT";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkPartitionParam("CREATE TABLE PKEY_SMALLINT ( PKEY SMALLINT NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_SMALLINT ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamSmallint;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamSmallint ON 'PKEY_SMALLINT.PKEY: 0';",
+ "PKEY_SMALLINT");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.NotAnnotatedPartitionParamSmallint may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.SMALLINT and partition parameter " +
+ "is type VoltType.BIGINT";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
fbs = checkPartitionParam("CREATE TABLE PKEY_TINYINT ( PKEY TINYINT NOT NULL, PRIMARY KEY (PKEY) );" +
- "PARTITION TABLE PKEY_TINYINT ON COLUMN PKEY;",
+ "PARTITION TABLE PKEY_TINYINT ON COLUMN PKEY;",
"org.voltdb.compiler.procedures.PartitionParamTinyint",
"PKEY_TINYINT");
expectedError =
@@ -178,8 +245,31 @@ public void testMismatchedPartitionParams() throws IOException {
"is type VoltType.SMALLINT";
assertTrue(isFeedbackPresent(expectedError, fbs));
+ fbs = checkPartitionParam("CREATE TABLE PKEY_TINYINT ( PKEY TINYINT NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_TINYINT ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.PartitionParamTinyint;",
+ "PKEY_TINYINT");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.PartitionParamTinyint may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.TINYINT and partition parameter " +
+ "is type VoltType.SMALLINT";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkPartitionParam("CREATE TABLE PKEY_TINYINT ( PKEY TINYINT NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_TINYINT ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamTinyint;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamTinyint ON 'PKEY_TINYINT.PKEY: 0';",
+ "PKEY_TINYINT");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.NotAnnotatedPartitionParamTinyint may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.TINYINT and partition parameter " +
+ "is type VoltType.SMALLINT";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
fbs = checkPartitionParam("CREATE TABLE PKEY_STRING ( PKEY VARCHAR(32) NOT NULL, PRIMARY KEY (PKEY) );" +
- "PARTITION TABLE PKEY_STRING ON COLUMN PKEY;",
+ "PARTITION TABLE PKEY_STRING ON COLUMN PKEY;",
"org.voltdb.compiler.procedures.PartitionParamString",
"PKEY_STRING");
expectedError =
@@ -188,6 +278,30 @@ public void testMismatchedPartitionParams() throws IOException {
"Partition column is type VoltType.STRING and partition parameter " +
"is type VoltType.INTEGER";
assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkPartitionParam("CREATE TABLE PKEY_STRING ( PKEY VARCHAR(32) NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_STRING ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.PartitionParamString;",
+ "PKEY_STRING");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.PartitionParamString may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.STRING and partition parameter " +
+ "is type VoltType.INTEGER";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkPartitionParam("CREATE TABLE PKEY_STRING ( PKEY VARCHAR(32) NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_STRING ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamString;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamString ON 'PKEY_STRING.PKEY: 0';",
+ "PKEY_STRING");
+ expectedError =
+ "Type mismatch between partition column and partition parameter for procedure " +
+ "org.voltdb.compiler.procedures.NotAnnotatedPartitionParamString may cause overflow or loss of precision.\n" +
+ "Partition column is type VoltType.STRING and partition parameter " +
+ "is type VoltType.INTEGER";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
}
@@ -218,6 +332,31 @@ public void testMismatchedPartitionParams() throws IOException {
return compiler.m_errors;
}
+ private ArrayList<Feedback> checkPartitionParam(String ddl, String table) {
+ final File schemaFile = VoltProjectBuilder.writeStringToTempFile(ddl);
+ final String schemaPath = schemaFile.getPath();
+
+ final String simpleProject =
+ "<?xml version=\"1.0\"?>\n" +
+ "<project>" +
+ "<database name='database'>" +
+ "<schemas>" +
+ "<schema path='" + schemaPath + "' />" +
+ "</schemas>" +
+ "<procedures/>" +
+ "</database>" +
+ "</project>";
+
+ final File projectFile = VoltProjectBuilder.writeStringToTempFile(simpleProject);
+ final String projectPath = projectFile.getPath();
+
+ final VoltCompiler compiler = new VoltCompiler();
+
+ final boolean success = compiler.compile(projectPath, testout_jar);
+ assertFalse(success);
+ return compiler.m_errors;
+ }
+
public void testSnapshotSettings() throws IOException {
String schemaPath = "";
try {
@@ -299,7 +438,7 @@ public void testExportTableCase() throws IOException {
final VoltProjectBuilder project = new VoltProjectBuilder();
project.addSchema(TestVoltCompiler.class.getResource("ExportTester-ddl.sql"));
project.addStmtProcedure("Dummy", "insert into a values (?, ?, ?);",
- "a.a_id: 0");
+ "a.a_id: 0");
project.addPartitionInfo("A", "A_ID");
project.addPartitionInfo("B", "B_ID");
project.addPartitionInfo("e", "e_id");
@@ -374,15 +513,15 @@ public void testXSDSchemaOrdering() throws IOException {
final String schemaPath = schemaFile.getPath();
final String project = "<?xml version=\"1.0\"?>\n" +
"<project>" +
- "<database>" +
+ "<database>" +
"<schemas>" +
- "<schema path='" + schemaPath + "'/>" +
+ "<schema path='" + schemaPath + "'/>" +
"</schemas>" +
"<procedures>" +
- "<procedure class='proc'><sql>select * from T</sql></procedure>" +
+ "<procedure class='proc'><sql>select * from T</sql></procedure>" +
"</procedures>" +
- "</database>" +
- "<security enabled='true'/>" +
+ "</database>" +
+ "<security enabled='true'/>" +
"</project>";
final File xmlFile = VoltProjectBuilder.writeStringToTempFile(project);
final String path = xmlFile.getPath();
@@ -885,6 +1024,50 @@ public void testOverrideProcInfo() throws IOException {
assertEquals(true, addBook.getSinglepartition());
}
+ public void testOverrideNonAnnotatedProcInfo() throws IOException {
+ final String simpleSchema =
+ "create table books (cash integer default 23 not null, title varchar(3) default 'foo', PRIMARY KEY(cash));" +
+ "PARTITION TABLE books ON COLUMN cash;" +
+ "create procedure from class org.voltdb.compiler.procedures.AddBook;" +
+ "partition procedure AddBook ON 'books.cash: 0';";
+
+ final File schemaFile = VoltProjectBuilder.writeStringToTempFile(simpleSchema);
+ final String schemaPath = schemaFile.getPath();
+
+ final String simpleProject =
+ "<?xml version=\"1.0\"?>\n" +
+ "<project>" +
+ "<database name='database'>" +
+ "<schemas><schema path='" + schemaPath + "' /></schemas>" +
+ "<procedures/>" +
+ "</database>" +
+ "</project>";
+
+ final File projectFile = VoltProjectBuilder.writeStringToTempFile(simpleProject);
+ final String projectPath = projectFile.getPath();
+
+ final ProcInfoData info = new ProcInfoData();
+ info.singlePartition = true;
+ info.partitionInfo = "BOOKS.CASH: 0";
+ final Map<String, ProcInfoData> overrideMap = new HashMap<String, ProcInfoData>();
+ overrideMap.put("AddBook", info);
+
+ final VoltCompiler compiler = new VoltCompiler();
+ compiler.setProcInfoOverrides(overrideMap);
+ final boolean success = compiler.compile(projectPath, testout_jar);
+
+ assertTrue(success);
+
+ final String catalogContents = VoltCompiler.readFileFromJarfile(testout_jar, "catalog.txt");
+
+ final Catalog c2 = new Catalog();
+ c2.execute(catalogContents);
+
+ final Database db = c2.getClusters().get("cluster").getDatabases().get("database");
+ final Procedure addBook = db.getProcedures().get("AddBook");
+ assertEquals(true, addBook.getSinglepartition());
+ }
+
public void testBadStmtProcName() throws IOException {
final String simpleSchema =
"create table books (cash integer default 23 not null, title varchar(10) default 'foo', PRIMARY KEY(cash));";
@@ -1253,16 +1436,16 @@ public void testDDLCompilerEscapedStringLiterals() throws IOException {
// be used in hash tables or array indexes
String[] column_types = {"tinyint", "smallint", "integer", "bigint",
- "float", "varchar(10)", "timestamp", "decimal"};
+ "float", "varchar(10)", "timestamp", "decimal"};
IndexType[] default_index_types = {IndexType.BALANCED_TREE,
- IndexType.BALANCED_TREE,
- IndexType.BALANCED_TREE,
- IndexType.BALANCED_TREE,
- IndexType.BALANCED_TREE,
- IndexType.BALANCED_TREE,
- IndexType.BALANCED_TREE,
- IndexType.BALANCED_TREE};
+ IndexType.BALANCED_TREE,
+ IndexType.BALANCED_TREE,
+ IndexType.BALANCED_TREE,
+ IndexType.BALANCED_TREE,
+ IndexType.BALANCED_TREE,
+ IndexType.BALANCED_TREE,
+ IndexType.BALANCED_TREE};
boolean[] can_be_hash = {true, true, true, true, false, false, true, false};
boolean[] can_be_tree = {true, true, true, true, true, true, true, true};
@@ -1279,9 +1462,9 @@ public void testDDLCompilerIndexDefaultTypes()
assertFalse(c.hasErrors());
Database d = c.m_catalog.getClusters().get("cluster").getDatabases().get("database");
assertEquals(default_index_types[i].getValue(),
- d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_id").getType());
+ d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_id").getType());
assertEquals(default_index_types[i].getValue(),
- d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_idnum").getType());
+ d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_idnum").getType());
}
}
@@ -1300,9 +1483,9 @@ public void testDDLCompilerHashIndexAllowed()
assertFalse(c.hasErrors());
Database d = c.m_catalog.getClusters().get("cluster").getDatabases().get("database");
assertEquals(IndexType.HASH_TABLE.getValue(),
- d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_id_hash").getType());
+ d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_id_hash").getType());
assertEquals(IndexType.HASH_TABLE.getValue(),
- d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_idnum_hash").getType());
+ d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_idnum_hash").getType());
}
else
{
@@ -1336,9 +1519,9 @@ public void testDDLCompilerVarcharTreeIndexAllowed()
assertFalse(c.hasErrors());
Database d = c.m_catalog.getClusters().get("cluster").getDatabases().get("database");
assertEquals(IndexType.BALANCED_TREE.getValue(),
- d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_id_tree").getType());
+ d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_id_tree").getType());
assertEquals(IndexType.BALANCED_TREE.getValue(),
- d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_idnum_tree").getType());
+ d.getTables().getIgnoreCase("t").getIndexes().getIgnoreCase("idx_t_idnum_tree").getType());
}
}
@@ -1457,6 +1640,347 @@ public void testBadDDLErrorLineNumber() throws IOException {
}
}
+
+ public void testInvalidCreateProcedureDDL() throws Exception {
+ ArrayList<Feedback> fbs;
+ String expectedError;
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NonExistentPartitionParamInteger;" +
+ "PARTITION PROCEDURE NonExistentPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Cannot load class for procedure: org.voltdb.compiler.procedures.NonExistentPartitionParamInteger";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "PARTITION PROCEDURE NotDefinedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Partition in referencing an undefined procedure \"NotDefinedPartitionParamInteger\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.PartitionParamInteger;" +
+ "PARTITION PROCEDURE PartitionParamInteger ON 'PKEY_WHAAAT.PKEY: 0';"
+ );
+ expectedError = "PartitionParamInteger has partition properties defined both in class " +
+ "\"org.voltdb.compiler.procedures.PartitionParamInteger\" and in the schema defintion file(s)";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_WHAAAT.PKEY: 0';"
+ );
+ expectedError = "PartitionInfo for procedure " +
+ "org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger refers to a column " +
+ "in schema which can't be found.";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PSURROGATE: 0';"
+ );
+ expectedError = "PartitionInfo for procedure " +
+ "org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger refers to a column " +
+ "in schema which can't be found.";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 8';"
+ );
+ expectedError = "PartitionInfo specifies invalid parameter index for procedure: " +
+ "org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM GLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad CREATE PROCEDURE DDL statement: " +
+ "\"CREATE PROCEDURE FROM GLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger\"" +
+ ", expected syntax: \"CREATE PROCEDURE FROM CLASS <class-name>\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger FOR 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad PARTITION DDL statement: \"PARTITION PROCEDURE " +
+ "NotAnnotatedPartitionParamInteger FOR 'PKEY_INTEGER.PKEY: 0'\", " +
+ "expected syntax: PARTITION PROCEDURE <procedure> ON " +
+ "'<table>.<column>: <parameter-index-no>'";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER,PKEY, 0';"
+ );
+ expectedError = "Bad PARTITION DDL statement: \"PARTITION PROCEDURE " +
+ "NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER,PKEY, 0'\", " +
+ "expected syntax: PARTITION PROCEDURE <procedure> ON " +
+ "'<table>.<column>: <parameter-index-no>'";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: hello';"
+ );
+ expectedError = "Bad PARTITION DDL statement: \"PARTITION PROCEDURE " +
+ "NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: hello'\", " +
+ "expected syntax: PARTITION PROCEDURE <procedure> ON " +
+ "'<table>.<column>: <parameter-index-no>'";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROGEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: hello';"
+ );
+ expectedError = "Bad PARTITION DDL statement: " +
+ "\"PARTITION PROGEDURE NotAnnotatedPartitionParamInteger ON " +
+ "'PKEY_INTEGER.PKEY: hello'\", expected syntax: \"PARTITION TABLE <table> " +
+ "ON COLUMN <column>\" or \"PARTITION PROCEDURE <procedure> ON " +
+ "'<table>.<column>: <parameter-index-no>'\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE OUTOF CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: hello';"
+ );
+ expectedError = "Bad CREATE PROCEDURE DDL statement: " +
+ "\"CREATE PROCEDURE OUTOF CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger\"" +
+ ", expected syntax: \"CREATE PROCEDURE FROM CLASS <class-name>\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "MAKE PROCEDURE OUTOF CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: hello';"
+ );
+ expectedError = "DDL Error: \"unexpected token: MAKE\" in statement starting on lineno: 1";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE 1PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad indentifier in DDL: \"PARTITION TABLE 1PKEY_INTEGER ON COLUMN PKEY\" " +
+ "contains invalid identifier \"1PKEY_INTEGER\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN 2PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad indentifier in DDL: \"PARTITION TABLE PKEY_INTEGER ON COLUMN 2PKEY\" " +
+ "contains invalid identifier \"2PKEY\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS 0rg.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad indentifier in DDL: \""+
+ "CREATE PROCEDURE FROM CLASS 0rg.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger" +
+ "\" contains invalid identifier \"0rg.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.3compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad indentifier in DDL: \""+
+ "CREATE PROCEDURE FROM CLASS org.voltdb.3compiler.procedures.NotAnnotatedPartitionParamInteger" +
+ "\" contains invalid identifier \"org.voltdb.3compiler.procedures.NotAnnotatedPartitionParamInteger\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.4NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad indentifier in DDL: \""+
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.4NotAnnotatedPartitionParamInteger" +
+ "\" contains invalid identifier \"org.voltdb.compiler.procedures.4NotAnnotatedPartitionParamInteger\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE 5NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad indentifier in DDL: \""+
+ "PARTITION PROCEDURE 5NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.PKEY: 0'" +
+ "\" contains invalid identifier \"5NotAnnotatedPartitionParamInteger\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON '6PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad indentifier in DDL: \""+
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON '6PKEY_INTEGER.PKEY: 0'" +
+ "\" contains invalid identifier \"6PKEY_INTEGER\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.7PKEY: 0';"
+ );
+ expectedError = "Bad indentifier in DDL: \""+
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger ON 'PKEY_INTEGER.7PKEY: 0'" +
+ "\" contains invalid identifier \"7PKEY\"";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+
+ fbs = checkInvalidProcedureDDL(
+ "CREATE TABLE PKEY_INTEGER ( PKEY INTEGER NOT NULL, PRIMARY KEY (PKEY) );" +
+ "PARTITION TABLE PKEY_INTEGER ON COLUMN PKEY;" +
+ "CREATE PROCEDURE FROM CLASS org.voltdb.compiler.procedures.NotAnnotatedPartitionParamInteger;" +
+ "PARTITION PROCEDURE NotAnnotatedPartitionParamInteger TABLE PKEY_INTEGER ON 'PKEY_INTEGER.PKEY: 0';"
+ );
+ expectedError = "Bad PARTITION DDL statement: \"PARTITION PROCEDURE " +
+ "NotAnnotatedPartitionParamInteger TABLE PKEY_INTEGER ON 'PKEY_INTEGER.PKEY: 0'\", " +
+ "expected syntax: PARTITION PROCEDURE <procedure> ON " +
+ "'<table>.<column>: <parameter-index-no>'";
+ assertTrue(isFeedbackPresent(expectedError, fbs));
+ }
+
+ private ArrayList<Feedback> checkInvalidProcedureDDL(String ddl) {
+ final File schemaFile = VoltProjectBuilder.writeStringToTempFile(ddl);
+ final String schemaPath = schemaFile.getPath();
+
+ final String simpleProject =
+ "<?xml version=\"1.0\"?>\n" +
+ "<project>" +
+ "<database name='database'>" +
+ "<schemas>" +
+ "<schema path='" + schemaPath + "' />" +
+ "</schemas>" +
+ "<procedures/>" +
+ "</database>" +
+ "</project>";
+
+ final File projectFile = VoltProjectBuilder.writeStringToTempFile(simpleProject);
+ final String projectPath = projectFile.getPath();
+
+ final VoltCompiler compiler = new VoltCompiler();
+
+ final boolean success = compiler.compile(projectPath, testout_jar);
+ assertFalse(success);
+ return compiler.m_errors;
+ }
+
+ public void testValidAnnotatedProcedureDLL() throws Exception {
+ final String simpleSchema =
+ "create table books (cash integer default 23 not null, title varchar(3) default 'foo', PRIMARY KEY(cash));" +
+ "PARTITION TABLE books ON COLUMN cash;" +
+ "creAte PrOcEdUrE FrOm CLasS org.voltdb.compiler.procedures.AddBook;";
+
+ final File schemaFile = VoltProjectBuilder.writeStringToTempFile(simpleSchema);
+ final String schemaPath = schemaFile.getPath();
+
+ final String simpleProject =
+ "<?xml version=\"1.0\"?>\n" +
+ "<project>" +
+ "<database name='database'>" +
+ "<schemas><schema path='" + schemaPath + "' /></schemas>" +
+ "<procedures/>" +
+ "</database>" +
+ "</project>";
+
+ final File projectFile = VoltProjectBuilder.writeStringToTempFile(simpleProject);
+ final String projectPath = projectFile.getPath();
+
+ final VoltCompiler compiler = new VoltCompiler();
+ final boolean success = compiler.compile(projectPath, testout_jar);
+
+ assertTrue(success);
+
+ final String catalogContents = VoltCompiler.readFileFromJarfile(testout_jar, "catalog.txt");
+
+ final Catalog c2 = new Catalog();
+ c2.execute(catalogContents);
+
+ final Database db = c2.getClusters().get("cluster").getDatabases().get("database");
+ final Procedure addBook = db.getProcedures().get("AddBook");
+ assertEquals(true, addBook.getSinglepartition());
+ }
+
+ public void testValidNonAnnotatedProcedureDDL() throws Exception {
+ final String simpleSchema =
+ "create table books (cash integer default 23 not null, title varchar(3) default 'foo', PRIMARY KEY(cash));" +
+ "PARTITION TABLE books ON COLUMN cash;" +
+ "create procedure from class org.voltdb.compiler.procedures.NotAnnotatedAddBook;" +
+ "paRtItiOn prOcEdure NotAnnotatedAddBook On 'books.cash: 0';";
+
+ final File schemaFile = VoltProjectBuilder.writeStringToTempFile(simpleSchema);
+ final String schemaPath = schemaFile.getPath();
+
+ final String simpleProject =
+ "<?xml version=\"1.0\"?>\n" +
+ "<project>" +
+ "<database name='database'>" +
+ "<schemas><schema path='" + schemaPath + "' /></schemas>" +
+ "<procedures/>" +
+ "</database>" +
+ "</project>";
+
+ final File projectFile = VoltProjectBuilder.writeStringToTempFile(simpleProject);
+ final String projectPath = projectFile.getPath();
+
+ final VoltCompiler compiler = new VoltCompiler();
+ final boolean success = compiler.compile(projectPath, testout_jar);
+
+ assertTrue(success);
+
+ final String catalogContents = VoltCompiler.readFileFromJarfile(testout_jar, "catalog.txt");
+
+ final Catalog c2 = new Catalog();
+ c2.execute(catalogContents);
+
+ final Database db = c2.getClusters().get("cluster").getDatabases().get("database");
+ final Procedure addBook = db.getProcedures().get("NotAnnotatedAddBook");
+ assertEquals(true, addBook.getSinglepartition());
+ }
+
private int countStringsMatching(List<String> diagnostics, String pattern) {
int count = 0;
for (String string : diagnostics) {
View
44 tests/frontend/org/voltdb/compiler/procedures/NotAnnotatedAddBook.java
@@ -0,0 +1,44 @@
+/* This file is part of VoltDB.
+ * Copyright (C) 2008-2012 VoltDB Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.voltdb.compiler.procedures;
+
+import org.voltdb.SQLStmt;
+import org.voltdb.VoltProcedure;
+import org.voltdb.VoltTable;
+
+public class NotAnnotatedAddBook extends VoltProcedure {
+ class ExtraClass {
+ int x;
+ }
+
+ public final SQLStmt
+ sqlAddBook = new SQLStmt("insert into books (cash, title) values (?, ?);");
+
+ public VoltTable[] run(int isbn, String title, String author)
+ throws VoltAbortException {
+ voltQueueSQL(sqlAddBook, isbn, title);
+ voltExecuteSQL();
+ return null;
+ }
+}
View
32 tests/frontend/org/voltdb/compiler/procedures/NotAnnotatedEmptyProcedure.java
@@ -0,0 +1,32 @@
+/* This file is part of VoltDB.
+ * Copyright (C) 2008-2012 VoltDB Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.voltdb.compiler.procedures;
+
+import org.voltdb.VoltProcedure;
+
+public class NotAnnotatedEmptyProcedure extends VoltProcedure {
+ public long run(long isbn, String title, String author)
+ throws VoltAbortException {
+ return 1;
+ }
+}
View
34 tests/frontend/org/voltdb/compiler/procedures/NotAnnotatedPartitionParamBigint.java
@@ -0,0 +1,34 @@
+/* This file is part of VoltDB.
+ * Copyright (C) 2008-2012 VoltDB Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.voltdb.compiler.procedures;
+
+import org.voltdb.VoltProcedure;
+import org.voltdb.VoltTable;
+
+public class NotAnnotatedPartitionParamBigint extends VoltProcedure {
+ public VoltTable[] run(String id)
+ throws VoltAbortException {
+ return voltExecuteSQL();
+ }
+
+}
View
33 tests/frontend/org/voltdb/compiler/procedures/NotAnnotatedPartitionParamInteger.java
@@ -0,0 +1,33 @@
+/* This file is part of VoltDB.
+ * Copyright (C) 2008-2012 VoltDB Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.voltdb.compiler.procedures;
+
+import org.voltdb.VoltProcedure;
+import org.voltdb.VoltTable;
+
+public class NotAnnotatedPartitionParamInteger extends VoltProcedure {
+ public VoltTable[] run(long id)
+ throws VoltAbortException {
+ return voltExecuteSQL();
+ }
+}
View
33 tests/frontend/org/voltdb/compiler/procedures/NotAnnotatedPartitionParamSmallint.java
@@ -0,0 +1,33 @@
+/* This file is part of VoltDB.
+ * Copyright (C) 2008-2012 VoltDB Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.voltdb.compiler.procedures;
+
+import org.voltdb.VoltProcedure;
+import org.voltdb.VoltTable;
+
+public class NotAnnotatedPartitionParamSmallint extends VoltProcedure {
+ public VoltTable[] run(long id)
+ throws VoltAbortException {
+ return voltExecuteSQL();
+ }
+}
View
36 tests/frontend/org/voltdb/compiler/procedures/NotAnnotatedPartitionParamString.java
@@ -0,0 +1,36 @@
+/* This file is part of VoltDB.
+ * Copyright (C) 2008-2012 VoltDB Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.voltdb.compiler.procedures;
+
+import org.voltdb.VoltProcedure;
+import org.voltdb.VoltTable;
+
+public class NotAnnotatedPartitionParamString extends VoltProcedure {
+
+ public VoltTable[] run(int id)
+ throws VoltAbortException {
+ return voltExecuteSQL();
+ }
+
+}
View
34 tests/frontend/org/voltdb/compiler/procedures/NotAnnotatedPartitionParamTinyint.java
@@ -0,0 +1,34 @@
+/* This file is part of VoltDB.
+ * Copyright (C) 2008-2012 VoltDB Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.voltdb.compiler.procedures;
+
+import org.voltdb.VoltProcedure;
+import org.voltdb.VoltTable;
+
+public class NotAnnotatedPartitionParamTinyint extends VoltProcedure {
+ public VoltTable[] run(short id)
+ throws VoltAbortException {
+ return voltExecuteSQL();
+ }
+}
View
4 tests/frontend/org/voltdb/planner/PlannerTestAideDeCamp.java
@@ -42,7 +42,7 @@
import org.voltdb.compiler.DDLCompiler;
import org.voltdb.compiler.DatabaseEstimates;
import org.voltdb.compiler.StatementCompiler;
-import org.voltdb.compiler.TablePartitionMap;
+import org.voltdb.compiler.PartitionMap;
import org.voltdb.compiler.VoltCompiler;
import org.voltdb.plannodes.AbstractPlanNode;
import org.voltdb.plannodes.PlanNodeList;
@@ -81,7 +81,7 @@ public PlannerTestAideDeCamp(URL ddlurl, String basename) throws Exception {
VoltCompiler compiler = new VoltCompiler();
hsql = HSQLInterface.loadHsqldb();
//hsql.runDDLFile(schemaPath);
- TablePartitionMap partitionMap = new TablePartitionMap(compiler);
+ PartitionMap partitionMap = new PartitionMap(compiler);
DDLCompiler ddl_compiler = new DDLCompiler(compiler, hsql, partitionMap);
ddl_compiler.loadSchema(schemaPath);
ddl_compiler.compileToCatalog(catalog, db);
Please sign in to comment.
Something went wrong with that request. Please try again.