statement.substring(0,statement.length()-1))); // remove trailing semicolon
}
// group(1) -> table, group(2) -> column
String tableName = checkIdentifierStart(statementMatcher.group(1), statement);
String columnName = checkIdentifierStart(statementMatcher.group(2), statement);
VoltXMLElement tableXML = m_schema.findChild("table", tableName.toUpperCase());
if (tableXML != null) {
tableXML.attributes.put("partitioncolumn", columnName.toUpperCase());
// Column validity check done by VoltCompiler in post-processing
}
else {
throw m_compiler.new VoltCompilerException(String.format(
"Invalid PARTITION statement: table %s does not exist", tableName));
}
return true;
}
else if (PROCEDURE.equals(partitionee)) {
if (whichProcs != DdlProceduresToLoad.ALL_DDL_PROCEDURES) {
return true;
}
// matches if it is
// PARTITION PROCEDURE <procedure>
// ON TABLE <table> COLUMN <column> [PARAMETER <parameter-index-no>]
statementMatcher = partitionProcedurePattern.matcher(statement);
if ( ! statementMatcher.matches()) {
throw m_compiler.new VoltCompilerException(String.format(
"Invalid PARTITION statement: \"%s\", " +
"expected syntax: PARTITION PROCEDURE <procedure> ON "+
"TABLE <table> COLUMN <column> [PARAMETER <parameter-index-no>]",
statement.substring(0,statement.length()-1))); // remove trailing semicolon
}
// check the table portion of the partition info
String tableName = checkIdentifierStart(statementMatcher.group(2), statement);
// check the column portion of the partition info
String columnName = checkIdentifierStart(statementMatcher.group(3), statement);
// if not specified default parameter index to 0
String parameterNo = statementMatcher.group(4);
if (parameterNo == null) {
parameterNo = "0";
}
String partitionInfo = String.format("%s.%s: %s", tableName, columnName, parameterNo);
// procedureName -> group(1), partitionInfo -> group(2)
m_tracker.addProcedurePartitionInfoTo(
checkIdentifierStart(statementMatcher.group(1), statement),
partitionInfo
);
return true;
}
// 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
String tableName = checkIdentifierStart(statementMatcher.group(1), statement);
VoltXMLElement tableXML = m_schema.findChild("table", tableName.toUpperCase());
if (tableXML != null) {
tableXML.attributes.remove("partitioncolumn");
}
else {
throw m_compiler.new VoltCompilerException(String.format(
"Invalid REPLICATE statement: table %s does not exist", tableName));
}
return true;
}
// match IMPORT CLASS statements
statementMatcher = importClassPattern.matcher(statement);
if (statementMatcher.matches()) {
if (whichProcs == DdlProceduresToLoad.ALL_DDL_PROCEDURES) {
// Semi-hacky way of determining if we're doing a cluster-internal compilation.
// Command-line compilation will never have an InMemoryJarfile.
if (!(m_classLoader instanceof InMemoryJarfile.JarLoader)) {
// Only process the statement if this is not for the StatementPlanner
String classNameStr = statementMatcher.group(1);
// check that the match pattern is a valid match pattern
checkIdentifierWithWildcard(classNameStr, statement);
ClassNameMatchStatus matchStatus = m_classMatcher.addPattern(classNameStr);
if (matchStatus == ClassNameMatchStatus.NO_EXACT_MATCH) {
throw m_compiler.new VoltCompilerException(String.format(
"IMPORT CLASS not found: '%s'",
classNameStr)); // remove trailing semicolon
}
else if (matchStatus == ClassNameMatchStatus.NO_WILDCARD_MATCH) {
m_compiler.addWarn(String.format(
"IMPORT CLASS no match for wildcarded class: '%s'",
classNameStr), ddlStatement.lineNo);
}
}
else {
m_compiler.addInfo("Internal cluster recompilation ignoring IMPORT CLASS line: " +
statement);
}
// Need to track the IMPORT CLASS lines even on internal compiles so that
// we don't lose them from the DDL source. When the @UAC path goes away,
// we could change this.
m_tracker.addImportLine(statement);
}
return true;
}
// matches if it is CREATE ROLE [WITH <permission> [, <permission> ...]]
// group 1 is role name
// group 2 is comma-separated permission list or null if there is no WITH clause
statementMatcher = createRolePattern.matcher(statement);
if (statementMatcher.matches()) {
String roleName = statementMatcher.group(1).toLowerCase();
CatalogMap<Group> groupMap = db.getGroups();
if (groupMap.get(roleName) != null) {
throw m_compiler.new VoltCompilerException(String.format(
"Role name \"%s\" in CREATE ROLE statement already exists.",
roleName));
}
org.voltdb.catalog.Group catGroup = groupMap.add(roleName);
if (statementMatcher.group(2) != null) {
try {
EnumSet<Permission> permset =
Permission.getPermissionsFromAliases(Arrays.asList(StringUtils.split(statementMatcher.group(2), ',')));
Permission.setPermissionsInGroup(catGroup, permset);
} catch (IllegalArgumentException iaex) {
throw m_compiler.new VoltCompilerException(String.format(
"Invalid permission \"%s\" in CREATE ROLE statement: \"%s\", " +
"available permissions: %s", iaex.getMessage(),
statement.substring(0,statement.length()-1), // remove trailing semicolon
Permission.toListString()));
}
}
return true;
}
statementMatcher = exportPattern.matcher(statement);
if (statementMatcher.matches()) {
// check the table portion
String tableName = checkIdentifierStart(statementMatcher.group(1), statement);
VoltXMLElement tableXML = m_schema.findChild("table", tableName.toUpperCase());
if (tableXML != null) {
tableXML.attributes.put("export", "true");
}
else {
throw m_compiler.new VoltCompilerException(String.format(