use of org.voltdb.catalog.Group in project voltdb by VoltDB.
the class DropRole method processStatement.
@Override
protected boolean processStatement(DDLStatement ddlStatement, Database db, DdlProceduresToLoad whichProcs) throws VoltCompilerException {
// matches if it is DROP ROLE
// group 1 is role name
Matcher statementMatcher = SQLParser.matchDropRole(ddlStatement.statement);
if (!statementMatcher.matches()) {
return false;
}
String roleName = statementMatcher.group(1).toUpperCase();
boolean ifExists = (statementMatcher.group(2) != null);
CatalogMap<Group> groupMap = db.getGroups();
if (groupMap.get(roleName) == null) {
if (!ifExists) {
throw m_compiler.new VoltCompilerException(String.format("Role name \"%s\" in DROP ROLE statement does not exist.", roleName));
} else {
return true;
}
} else {
// dropped.
if (roleName.equals("ADMINISTRATOR") || roleName.equals("USER")) {
throw m_compiler.new VoltCompilerException(String.format("You may not drop the built-in role \"%s\".", roleName));
}
// The constraint that there be no users with this role gets
// checked by the deployment validation. *HOWEVER*, right now
// this ends up giving a confusing error message.
groupMap.delete(roleName);
}
return true;
}
use of org.voltdb.catalog.Group in project voltdb by VoltDB.
the class CatalogSchemaTools method toSchema.
/**
* Convert a catalog into a string containing all DDL statements.
* @param catalog
* @param importLines A set of importLines, should not be mutated.
* @return String of DDL statements.
*/
public static String toSchema(Catalog catalog, Set<String> importLines) {
StringBuilder sb = new StringBuilder();
sb.append("-- This file was generated by VoltDB version ");
sb.append(VoltDB.instance().getVersionString());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
String time = sdf.format(System.currentTimeMillis());
sb.append(" on: " + time + ".\n");
sb.append("-- This file represents the current database schema.\n");
sb.append("-- Use this file as input to reproduce the current database structure in another database instance.\n");
sb.append("--\n");
sb.append(batchSpecificComments);
sb.append("-- If the schema declares Java stored procedures, be sure to load the .jar file\n");
sb.append("-- with the classes before loading the schema. For example:\n");
sb.append("--\n");
sb.append("-- LOAD CLASSES voltdb-procs.jar;\n");
sb.append("-- FILE ddl.sql;\n");
for (Cluster cluster : catalog.getClusters()) {
for (Database db : cluster.getDatabases()) {
toSchema(sb, importLines);
for (Group grp : db.getGroups()) {
toSchema(sb, grp);
}
sb.append("\n");
List<Table> viewList = new ArrayList<>();
CatalogMap<Table> tables = db.getTables();
if (!tables.isEmpty()) {
sb.append(startBatch);
for (Table table : tables) {
Object annotation = table.getAnnotation();
if (annotation != null && ((TableAnnotation) annotation).ddl != null && table.getMaterializer() != null) {
viewList.add(table);
continue;
}
toSchema(sb, table, null, CatalogUtil.isTableExportOnly(db, table), (table.getPartitioncolumn() != null ? table.getPartitioncolumn().getName() : null), CatalogUtil.getExportTargetIfExportTableOrNullOtherwise(db, table));
}
// A View cannot precede a table that it depends on in the DDL
for (Table table : viewList) {
String viewQuery = ((TableAnnotation) table.getAnnotation()).ddl;
toSchema(sb, table, viewQuery, false, null, null);
}
}
CatalogMap<Procedure> procedures = db.getProcedures();
if (!procedures.isEmpty()) {
for (Procedure proc : procedures) {
toSchema(sb, proc);
}
}
CatalogMap<Function> functions = db.getFunctions();
if (!functions.isEmpty()) {
for (Function func : functions) {
toSchema(sb, func);
}
}
if (!tables.isEmpty()) {
sb.append(endBatch);
}
}
}
if (dumpSchema) {
String ts = new SimpleDateFormat("MMddHHmmssSSS").format(new Date());
File f = new File(String.format("/tmp/canonical-%s.sql", ts));
try {
FileWriter fw = new FileWriter(f);
fw.write(sb.toString());
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
use of org.voltdb.catalog.Group in project voltdb by VoltDB.
the class TestVoltCompiler method checkRoleDDL.
private void checkRoleDDL(String ddl, String errorRegex, TestRole... roles) throws Exception {
VoltCompiler compiler = new VoltCompiler(false);
final boolean success = compileDDL(ddl, compiler);
String error = (success || compiler.m_errors.size() == 0 ? "" : compiler.m_errors.get(compiler.m_errors.size() - 1).message);
if (errorRegex == null) {
assertTrue(String.format("Expected success\nDDL: %s\nERR: %s", ddl, error), success);
Database db = compiler.getCatalog().getClusters().get("cluster").getDatabases().get("database");
CatalogMap<Group> groups = db.getGroups();
CatalogMap<Connector> connectors = db.getConnectors();
if (connectors.get("0") == null) {
connectors.add("0");
}
assertNotNull(groups);
assertTrue(roles.length <= groups.size());
for (TestRole role : roles) {
Group group = groups.get(role.name);
assertNotNull(String.format("Missing role \"%s\"", role.name), group);
assertEquals(String.format("Role \"%s\" sql flag mismatch:", role.name), role.sql, group.getSql());
assertEquals(String.format("Role \"%s\" sqlread flag mismatch:", role.name), role.sqlread, group.getSqlread());
assertEquals(String.format("Role \"%s\" admin flag mismatch:", role.name), role.sysproc, group.getAdmin());
assertEquals(String.format("Role \"%s\" defaultproc flag mismatch:", role.name), role.defaultproc, group.getDefaultproc());
assertEquals(String.format("Role \"%s\" defaultprocread flag mismatch:", role.name), role.defaultprocread, group.getDefaultprocread());
assertEquals(String.format("Role \"%s\" allproc flag mismatch:", role.name), role.allproc, group.getAllproc());
}
} else {
assertFalse(String.format("Expected error (\"%s\")\n\nDDL: %s", errorRegex, ddl), success);
assertFalse("Expected at least one error message.", error.isEmpty());
Matcher m = Pattern.compile(errorRegex).matcher(error);
assertTrue(String.format("%s\nEXPECTED: %s", error, errorRegex), m.matches());
}
}
use of org.voltdb.catalog.Group in project voltdb by VoltDB.
the class ProcedureCompiler method compileSingleStmtProcedure.
static void compileSingleStmtProcedure(VoltCompiler compiler, HSQLInterface hsql, DatabaseEstimates estimates, Database db, ProcedureDescriptor procedureDescriptor) throws VoltCompiler.VoltCompilerException {
final String className = procedureDescriptor.m_className;
if (className.indexOf('@') != -1) {
throw compiler.new VoltCompilerException("User procedure names can't contain \"@\".");
}
// get the short name of the class (no package if a user procedure)
// use the Table.<builtin> name (allowing the period) if builtin.
String shortName = className;
if (procedureDescriptor.m_builtInStmt == false) {
String[] parts = className.split("\\.");
shortName = parts[parts.length - 1];
}
// add an entry to the catalog (using the full className)
final Procedure procedure = db.getProcedures().add(shortName);
for (String groupName : procedureDescriptor.m_authGroups) {
final Group group = db.getGroups().get(groupName);
if (group == null) {
throw compiler.new VoltCompilerException("Procedure " + className + " allows access by a role " + groupName + " that does not exist");
}
final GroupRef groupRef = procedure.getAuthgroups().add(groupName);
groupRef.setGroup(group);
}
procedure.setClassname(className);
// sysprocs don't use the procedure compiler
procedure.setSystemproc(false);
procedure.setDefaultproc(procedureDescriptor.m_builtInStmt);
procedure.setHasjava(false);
procedure.setTransactional(true);
// get the annotation
// first try to get one that has been passed from the compiler
ProcInfoData info = compiler.getProcInfoOverride(shortName);
// and create a ProcInfo.Data instance for it
if (info == null) {
info = new ProcInfoData();
if (procedureDescriptor.m_partitionString != null) {
info.partitionInfo = procedureDescriptor.m_partitionString;
info.singlePartition = true;
}
}
assert (info != null);
// ADD THE STATEMENT
// add the statement to the catalog
Statement catalogStmt = procedure.getStatements().add(VoltDB.ANON_STMT_NAME);
// compile the statement
StatementPartitioning partitioning = info.singlePartition ? StatementPartitioning.forceSP() : StatementPartitioning.forceMP();
// default to FASTER detmode because stmt procs can't feed read output into writes
StatementCompiler.compileFromSqlTextAndUpdateCatalog(compiler, hsql, db, estimates, catalogStmt, procedureDescriptor.m_singleStmt, procedureDescriptor.m_joinOrder, DeterminismMode.FASTER, partitioning);
// if the single stmt is not read only, then the proc is not read only
boolean procHasWriteStmts = (catalogStmt.getReadonly() == false);
// set the read onlyness of a proc
procedure.setReadonly(procHasWriteStmts == false);
int seqs = catalogStmt.getSeqscancount();
procedure.setHasseqscans(seqs > 0);
// set procedure parameter types
CatalogMap<ProcParameter> params = procedure.getParameters();
CatalogMap<StmtParameter> stmtParams = catalogStmt.getParameters();
// set the procedure parameter types from the statement parameter types
int paramCount = 0;
for (StmtParameter stmtParam : CatalogUtil.getSortedCatalogItems(stmtParams, "index")) {
// name each parameter "param1", "param2", etc...
ProcParameter procParam = params.add("param" + String.valueOf(paramCount));
procParam.setIndex(stmtParam.getIndex());
procParam.setIsarray(stmtParam.getIsarray());
procParam.setType(stmtParam.getJavatype());
paramCount++;
}
// parse the procinfo
procedure.setSinglepartition(info.singlePartition);
if (info.singlePartition) {
parsePartitionInfo(compiler, db, procedure, info.partitionInfo);
if (procedure.getPartitionparameter() >= params.size()) {
String msg = "PartitionInfo parameter not a valid parameter for procedure: " + procedure.getClassname();
throw compiler.new VoltCompilerException(msg);
}
// TODO: The planner does not currently validate that a single-statement plan declared as single-partition correctly uses
// the designated parameter as a partitioning filter, maybe some day.
// In theory, the PartitioningForStatement would confirm the use of (only) a parameter as a partition key --
// or if the partition key was determined to be some other hard-coded constant (expression?) it might display a warning
// message that the passed parameter is assumed to be equal to that constant (expression).
} else {
if (partitioning.getCountOfIndependentlyPartitionedTables() == 1) {
AbstractExpression statementPartitionExpression = partitioning.singlePartitioningExpressionForReport();
if (statementPartitionExpression != null) {
// The planner has uncovered an overlooked opportunity to run the statement SP.
String msg = "This procedure " + shortName + " would benefit from being partitioned, by ";
String tableName = "tableName", partitionColumnName = "partitionColumnName";
try {
assert (partitioning.getFullColumnName() != null);
String[] array = partitioning.getFullColumnName().split("\\.");
tableName = array[0];
partitionColumnName = array[1];
} catch (Exception ex) {
}
if (statementPartitionExpression instanceof ParameterValueExpression) {
paramCount = ((ParameterValueExpression) statementPartitionExpression).getParameterIndex();
} else {
String valueDescription = null;
Object partitionValue = partitioning.getInferredPartitioningValue();
if (partitionValue == null) {
// Statement partitioned on a runtime constant. This is likely to be cryptic, but hopefully gets the idea across.
valueDescription = "of " + statementPartitionExpression.explain("");
} else {
// A simple constant value COULD have been a parameter.
valueDescription = partitionValue.toString();
}
msg += "adding a parameter to be passed the value " + valueDescription + " and ";
}
msg += "adding a 'PARTITION ON TABLE " + tableName + " COLUMN " + partitionColumnName + " PARAMETER " + paramCount + "' clause to the " + "CREATE PROCEDURE statement. or using a separate PARTITION PROCEDURE statement";
compiler.addWarn(msg);
}
}
}
}
use of org.voltdb.catalog.Group in project voltdb by VoltDB.
the class TestPermission method testPermissionsFromGroup.
@Test
public void testPermissionsFromGroup() {
Group group = new Group();
final EnumSet<Permission> none = Permission.getPermissionSetForGroup(group);
group = new Group();
group.setSql(true);
final EnumSet<Permission> sql = Permission.getPermissionSetForGroup(group);
group = new Group();
group.setSqlread(true);
final EnumSet<Permission> sqlread = Permission.getPermissionSetForGroup(group);
group = new Group();
group.setDefaultproc(true);
final EnumSet<Permission> defaultproc = Permission.getPermissionSetForGroup(group);
group = new Group();
group.setAdmin(true);
final EnumSet<Permission> admin = Permission.getPermissionSetForGroup(group);
group = new Group();
group.setSql(true);
group.setDefaultprocread(true);
group.setDefaultproc(true);
final EnumSet<Permission> allthree = Permission.getPermissionSetForGroup(group);
group = new Group();
group.setSql(true);
group.setDefaultproc(true);
group.setAdmin(true);
final EnumSet<Permission> mixed = Permission.getPermissionSetForGroup(group);
verify(none, sql, sqlread, defaultproc, admin, admin, allthree, mixed);
}
Aggregations