use of org.voltdb.catalog.Procedure 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.Procedure in project voltdb by VoltDB.
the class TestInvocationAcceptancePolicy method testUserPermission.
@Test
public void testUserPermission() {
Procedure proc = new Procedure();
proc.setDefaultproc(true);
AuthSystem.AuthUser user = createUser(false, true, false, proc, true, false, false);
StoredProcedureInvocation invocation = new StoredProcedureInvocation();
invocation.setProcName("A.insert");
invocation.setParams("test");
InvocationPermissionPolicy policy = new InvocationDefaultProcPermissionPolicy();
assertEquals(policy.shouldAccept(user, invocation, proc), PolicyResult.ALLOW);
// A user that doesn't have crud permission
user = createUser(false, false, false, null, true, false, false);
assertEquals(policy.shouldAccept(user, invocation, proc), PolicyResult.DENY);
}
use of org.voltdb.catalog.Procedure in project voltdb by VoltDB.
the class TestInvocationAcceptancePolicy method testAdHocUserPermission.
@Test
public void testAdHocUserPermission() {
AuthSystem.AuthUser user = createUser(true, false, false, null, true, false, false);
StoredProcedureInvocation invocation = new StoredProcedureInvocation();
invocation.setProcName("@AdHoc_RW_MP");
invocation.setParams("insert into T values (1);");
Procedure proc = SystemProcedureCatalog.listing.get("@AdHoc_RW_MP").asCatalogProcedure();
InvocationPermissionPolicy policy = new InvocationSqlPermissionPolicy();
assertEquals(policy.shouldAccept(user, invocation, proc), PolicyResult.ALLOW);
// A user that doesn't have adhoc permission
user = createUser(false, false, false, null, true, true, true);
assertEquals(policy.shouldAccept(user, invocation, proc), PolicyResult.DENY);
}
use of org.voltdb.catalog.Procedure in project voltdb by VoltDB.
the class TestInvocationAcceptancePolicy method testUserDefinedProcPermission.
@Test
public void testUserDefinedProcPermission() {
Procedure proc = new Procedure();
StoredProcedureInvocation invocation = new StoredProcedureInvocation();
invocation.setProcName("MyProc");
invocation.setParams("test");
InvocationPermissionPolicy policy = new InvocationUserDefinedProcedurePermissionPolicy();
//WITH allproc access
AuthSystem.AuthUser user2 = createUser(false, false, false, proc, true, true, true);
assertEquals(policy.shouldAccept(user2, invocation, proc), PolicyResult.ALLOW);
//Without allproc
AuthSystem.AuthUser user3 = createUser(false, false, false, proc, false, false, false);
assertEquals(policy.shouldAccept(user3, invocation, proc), PolicyResult.DENY);
//We cant test individual authorized proc here.
}
use of org.voltdb.catalog.Procedure in project voltdb by VoltDB.
the class TestInvocationAcceptancePolicy method testSysprocUserPermission.
@Test
public void testSysprocUserPermission() {
AuthSystem.AuthUser user = createUser(false, false, true, null, true, false, false);
StoredProcedureInvocation invocation = new StoredProcedureInvocation();
invocation.setProcName("@Pause");
Procedure proc = SystemProcedureCatalog.listing.get("@Pause").asCatalogProcedure();
InvocationPermissionPolicy policy = new InvocationSysprocPermissionPolicy();
assertEquals(policy.shouldAccept(user, invocation, proc), PolicyResult.ALLOW);
// A user that doesn't have admin permission
user = createUser(false, false, false, null, true, false, false);
assertEquals(policy.shouldAccept(user, invocation, proc), PolicyResult.DENY);
}
Aggregations