use of org.voltdb.catalog.GroupRef 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.GroupRef in project voltdb by VoltDB.
the class SystemInformation method populateDeploymentProperties.
public static VoltTable populateDeploymentProperties(Cluster cluster, Database database, ClusterSettings clusterSettings, NodeSettings nodeSettings) {
VoltTable results = new VoltTable(clusterInfoSchema);
// it would be awesome if these property names could come
// from the RestApiDescription.xml (or the equivalent thereof) someday --izzy
results.addRow("voltdbroot", VoltDB.instance().getVoltDBRootPath());
Deployment deploy = cluster.getDeployment().get("deployment");
results.addRow("hostcount", Integer.toString(clusterSettings.hostcount()));
results.addRow("kfactor", Integer.toString(deploy.getKfactor()));
results.addRow("sitesperhost", Integer.toString(nodeSettings.getLocalSitesCount()));
String http_enabled = "false";
int http_port = VoltDB.instance().getConfig().m_httpPort;
if (http_port != -1 && http_port != Integer.MAX_VALUE) {
http_enabled = "true";
results.addRow("httpport", Integer.toString(http_port));
}
results.addRow("httpenabled", http_enabled);
String json_enabled = "false";
if (cluster.getJsonapi()) {
json_enabled = "true";
}
results.addRow("jsonenabled", json_enabled);
SnapshotSchedule snaps = database.getSnapshotschedule().get("default");
String snap_enabled = "false";
if (snaps != null && snaps.getEnabled()) {
snap_enabled = "true";
String snap_freq = Integer.toString(snaps.getFrequencyvalue()) + snaps.getFrequencyunit();
results.addRow("snapshotpath", VoltDB.instance().getSnapshotPath());
results.addRow("snapshotprefix", snaps.getPrefix());
results.addRow("snapshotfrequency", snap_freq);
results.addRow("snapshotretain", Integer.toString(snaps.getRetain()));
}
results.addRow("snapshotenabled", snap_enabled);
for (Connector export_conn : database.getConnectors()) {
if (export_conn != null && export_conn.getEnabled()) {
results.addRow("exportoverflowpath", VoltDB.instance().getExportOverflowPath());
break;
}
}
results.addRow("export", Boolean.toString(CatalogUtil.isExportEnabled()));
String partition_detect_enabled = "false";
if (cluster.getNetworkpartition()) {
partition_detect_enabled = "true";
}
results.addRow("partitiondetection", partition_detect_enabled);
results.addRow("heartbeattimeout", Integer.toString(cluster.getHeartbeattimeout()));
results.addRow("adminport", Integer.toString(VoltDB.instance().getConfig().m_adminPort));
String command_log_enabled = "false";
// log name is MAGIC, you knoooow
CommandLog command_log = cluster.getLogconfig().get("log");
if (command_log.getEnabled()) {
command_log_enabled = "true";
String command_log_mode = "async";
if (command_log.getSynchronous()) {
command_log_mode = "sync";
}
String command_log_path = VoltDB.instance().getCommandLogPath();
String command_log_snaps = VoltDB.instance().getCommandLogSnapshotPath();
String command_log_fsync_interval = Integer.toString(command_log.getFsyncinterval());
String command_log_max_txns = Integer.toString(command_log.getMaxtxns());
results.addRow("commandlogmode", command_log_mode);
results.addRow("commandlogfreqtime", command_log_fsync_interval);
results.addRow("commandlogfreqtxns", command_log_max_txns);
results.addRow("commandlogpath", command_log_path);
results.addRow("commandlogsnapshotpath", command_log_snaps);
}
results.addRow("commandlogenabled", command_log_enabled);
String users = "";
for (User user : database.getUsers()) {
users += addEscapes(user.getTypeName());
if (user.getGroups() != null && user.getGroups().size() > 0) {
users += ":";
for (GroupRef gref : user.getGroups()) {
users += addEscapes(gref.getGroup().getTypeName());
users += ",";
}
users = users.substring(0, users.length() - 1);
}
users += ";";
}
results.addRow("users", users);
// Add system setting information also
// the attribute names follows the above naming rule
Systemsettings sysSettings = deploy.getSystemsettings().get("systemsettings");
results.addRow("elasticduration", Integer.toString(sysSettings.getElasticduration()));
results.addRow("elasticthroughput", Integer.toString(sysSettings.getElasticthroughput()));
results.addRow("snapshotpriority", Integer.toString(sysSettings.getSnapshotpriority()));
results.addRow("temptablesmaxsize", Integer.toString(sysSettings.getTemptablemaxsize()));
results.addRow("querytimeout", Integer.toString(sysSettings.getQuerytimeout()));
return results;
}
use of org.voltdb.catalog.GroupRef in project voltdb by VoltDB.
the class CatalogSchemaTools method toSchema.
/**
* Convert a Catalog Procedure into a DDL string.
* @param proc
*/
public static void toSchema(StringBuilder sb, Procedure proc) {
// JAVA: hasJava (true, m_defaultproc (false)
if (proc.getDefaultproc()) {
return;
}
// Build the optional ALLOW clause.
CatalogMap<GroupRef> roleList = proc.getAuthgroups();
String add;
String allowClause = new String();
if (roleList.size() > 0) {
add = "\n" + spacer + "ALLOW ";
for (GroupRef role : roleList) {
allowClause += add + role.getGroup().getTypeName();
add = ", ";
}
}
// Build the optional PARTITION clause.
StringBuilder partitionClause = new StringBuilder();
ProcedureAnnotation annot = (ProcedureAnnotation) proc.getAnnotation();
if (proc.getSinglepartition()) {
if (annot != null && annot.classAnnotated) {
partitionClause.append("--Annotated Partitioning Takes Precedence Over DDL Procedure Partitioning Statement\n--");
} else {
partitionClause.append("\n");
}
partitionClause.append(spacer);
partitionClause.append(String.format("PARTITION ON TABLE %s COLUMN %s", proc.getPartitiontable().getTypeName(), proc.getPartitioncolumn().getTypeName()));
if (proc.getPartitionparameter() != 0) {
partitionClause.append(String.format(" PARAMETER %s", String.valueOf(proc.getPartitionparameter())));
}
}
// Build the appropriate CREATE PROCEDURE statement variant.
if (!proc.getHasjava()) {
// SQL Statement procedure
sb.append(String.format("CREATE PROCEDURE %s%s%s\n%sAS\n%s%s", proc.getClassname(), allowClause, partitionClause.toString(), spacer, spacer, proc.getStatements().get("SQL").getSqltext().trim()));
} else {
// Java Class
sb.append(String.format("CREATE PROCEDURE %s%s\n%sFROM CLASS %s", allowClause, partitionClause.toString(), spacer, proc.getClassname()));
}
// The SQL statement variant may have terminated the CREATE PROCEDURE statement.
if (!sb.toString().endsWith(";")) {
sb.append(";");
}
// Give me some space man.
sb.append("\n\n");
}
use of org.voltdb.catalog.GroupRef in project voltdb by VoltDB.
the class ReportMaker method generateProcedureRow.
static String generateProcedureRow(CatalogMap<Table> tables, Procedure procedure) {
StringBuilder sb = new StringBuilder();
sb.append("<tr class='primaryrow'>");
// column 1: procedure name
String anchor = procedure.getTypeName().toLowerCase();
sb.append("<td style='white-space: nowrap'><i id='p-" + anchor + "--icon' class='icon-chevron-right'></i> <a href='#p-");
sb.append(anchor).append("' id='p-").append(anchor).append("' class='togglex'>");
sb.append(procedure.getTypeName());
sb.append("</a></td>");
// column 2: parameter types
sb.append("<td>");
List<ProcParameter> params = CatalogUtil.getSortedCatalogItems(procedure.getParameters(), "index");
List<String> paramTypes = new ArrayList<String>();
for (ProcParameter param : params) {
String paramType = VoltType.get((byte) param.getType()).name();
if (param.getIsarray()) {
paramType += "[]";
}
paramTypes.add(paramType);
}
if (paramTypes.size() == 0) {
sb.append("<i>None</i>");
}
sb.append(StringUtils.join(paramTypes, ", "));
sb.append("</td>");
// column 3: partitioning
sb.append("<td>");
if (procedure.getSinglepartition()) {
tag(sb, "success", "Single");
} else {
tag(sb, "warning", "Multi");
}
sb.append("</td>");
// column 4: read/write
sb.append("<td>");
if (procedure.getReadonly()) {
tag(sb, "success", "Read");
} else {
tag(sb, "warning", "Write");
}
sb.append("</td>");
// column 5: access
sb.append("<td>");
List<String> groupNames = new ArrayList<String>();
for (GroupRef groupRef : procedure.getAuthgroups()) {
groupNames.add(groupRef.getGroup().getTypeName());
}
if (groupNames.size() == 0) {
sb.append("<i>None</i>");
}
sb.append(StringUtils.join(groupNames, ", "));
sb.append("</td>");
// column 6: attributes
sb.append("<td>");
if (procedure.getHasjava()) {
tag(sb, "info", "Java");
} else {
tag(sb, null, "Single-Stmt");
}
boolean isND = false;
int scanCount = 0;
for (Statement stmt : procedure.getStatements()) {
scanCount += stmt.getSeqscancount();
if (!stmt.getIscontentdeterministic() || !stmt.getIsorderdeterministic()) {
isND = false;
}
}
if (isND) {
tag(sb, "inverse", "Determinism");
}
if (scanCount > 0) {
tag(sb, "important", "Scans");
}
sb.append("</td>");
sb.append("</tr>\n");
// BUILD THE DROPDOWN FOR THE STATEMENT/DETAIL TABLE
sb.append("<tr class='tablesorter-childRow'><td class='invert' colspan='6' id='p-" + procedure.getTypeName().toLowerCase() + "--dropdown'>\n");
// output partitioning parameter info
if (procedure.getSinglepartition()) {
String pTable = procedure.getPartitioncolumn().getParent().getTypeName();
String pColumn = procedure.getPartitioncolumn().getTypeName();
int pIndex = procedure.getPartitionparameter();
sb.append(String.format("<p>Partitioned on parameter %d which maps to column %s" + " of table <a class='invert' href='#s-%s'>%s</a>.</p>", pIndex, pColumn, pTable, pTable));
}
// get the annotation or ensure it's there
ProcedureAnnotation annotation = (ProcedureAnnotation) procedure.getAnnotation();
if (annotation == null) {
annotation = new ProcedureAnnotation();
procedure.setAnnotation(annotation);
}
// this needs to be run before the ProcedureAnnotation is used below
// because it modifies it
String statementsTable = generateStatementsTable(tables, procedure);
// output what schema this interacts with
// make sure tables appear in only one category
annotation.tablesRead.removeAll(annotation.tablesUpdated);
if (annotation.tablesRead.size() > 0) {
sb.append("<p>Read-only access to tables: ");
List<String> tableList = new ArrayList<String>();
for (Table table : annotation.tablesRead) {
tableList.add("<a href='#s-" + table.getTypeName() + "'>" + table.getTypeName() + "</a>");
}
sb.append(StringUtils.join(tableList, ", "));
sb.append("</p>");
}
if (annotation.tablesUpdated.size() > 0) {
sb.append("<p>Read/Write access to tables: ");
List<String> tableList = new ArrayList<String>();
for (Table table : annotation.tablesUpdated) {
tableList.add("<a href='#s-" + table.getTypeName() + "'>" + table.getTypeName() + "</a>");
}
sb.append(StringUtils.join(tableList, ", "));
sb.append("</p>");
}
if (annotation.indexesUsed.size() > 0) {
sb.append("<p>Uses indexes: ");
List<String> indexes = new ArrayList<String>();
for (Index index : annotation.indexesUsed) {
Table table = (Table) index.getParent();
indexes.add("<a href='#s-" + table.getTypeName() + "-" + index.getTypeName() + "'>" + index.getTypeName() + "</a>");
}
sb.append(StringUtils.join(indexes, ", "));
sb.append("</p>");
}
sb.append(statementsTable);
sb.append("</td></tr>\n");
return sb.toString();
}
use of org.voltdb.catalog.GroupRef in project voltdb by VoltDB.
the class CatalogUtil method setUsersInfo.
/**
* Set user info in the catalog.
* @param catalog The catalog to be updated.
* @param users A reference to the <users> element of the deployment.xml file.
* @throws RuntimeException when there is an user with invalid masked password.
*/
private static void setUsersInfo(Catalog catalog, UsersType users) throws RuntimeException {
if (users == null) {
return;
}
// The database name is not available in deployment.xml (it is defined
// in project.xml). However, it must always be named "database", so
// I've temporarily hardcoded it here until a more robust solution is
// available.
Database db = catalog.getClusters().get("cluster").getDatabases().get("database");
SecureRandom sr = new SecureRandom();
for (UsersType.User user : users.getUser()) {
Set<String> roles = extractUserRoles(user);
String sha1hex = user.getPassword();
String sha256hex = user.getPassword();
if (user.isPlaintext()) {
sha1hex = extractPassword(user.getPassword(), ClientAuthScheme.HASH_SHA1);
sha256hex = extractPassword(user.getPassword(), ClientAuthScheme.HASH_SHA256);
} else if (user.getPassword().length() == 104) {
int sha1len = ClientAuthScheme.getHexencodedDigestLength(ClientAuthScheme.HASH_SHA1);
sha1hex = sha1hex.substring(0, sha1len);
sha256hex = sha256hex.substring(sha1len);
} else {
// if one user has invalid password, give a warn.
hostLog.warn("User \"" + user.getName() + "\" has invalid masked password in deployment file.");
// throw exception disable user with invalid masked password
throw new RuntimeException("User \"" + user.getName() + "\" has invalid masked password in deployment file");
}
org.voltdb.catalog.User catUser = db.getUsers().add(user.getName());
// generate salt only once for sha1 and sha256
String saltGen = BCrypt.gensalt(BCrypt.GENSALT_DEFAULT_LOG2_ROUNDS, sr);
String hashedPW = BCrypt.hashpw(sha1hex, saltGen);
String hashedPW256 = BCrypt.hashpw(sha256hex, saltGen);
catUser.setShadowpassword(hashedPW);
catUser.setSha256shadowpassword(hashedPW256);
// process the @groups and @roles comma separated list
for (final String role : roles) {
final Group catalogGroup = db.getGroups().get(role);
// if the role doesn't exist, ignore it.
if (catalogGroup != null) {
final GroupRef groupRef = catUser.getGroups().add(role);
groupRef.setGroup(catalogGroup);
} else {
hostLog.warn("User \"" + user.getName() + "\" is assigned to non-existent role \"" + role + "\" " + "and may not have the expected database permissions.");
}
}
}
}
Aggregations