use of org.voltdb.catalog.Statement 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.Statement in project voltdb by VoltDB.
the class MaterializedViewProcessor method compileCreateQueryAndUpdateCatalog.
private void compileCreateQueryAndUpdateCatalog(Database db, String query, VoltXMLElement xmlquery, MaterializedViewHandlerInfo mvHandlerInfo) throws VoltCompilerException {
DatabaseEstimates estimates = new DatabaseEstimates();
// Here we are compiling the query twice:
// In the first round, we will use inferPartitioning.
// The purpose is to use the planner to check if the join query is plannable.
// Some multi-partition join queries are not plannable because they are not
// joining tables on the partition columns.
// In the second round, we will use forceSP to get the single partition
// version of the query plan.
Statement createQueryInfer = mvHandlerInfo.getCreatequery().add("createQueryInfer");
Statement createQuery = mvHandlerInfo.getCreatequery().add("createQuery");
createQueryInfer.setSqltext(query);
createQuery.setSqltext(query);
StatementCompiler.compileStatementAndUpdateCatalog(m_compiler, m_hsql, db, estimates, createQueryInfer, xmlquery, createQueryInfer.getSqltext(), // no user-supplied join order
null, DeterminismMode.FASTER, StatementPartitioning.inferPartitioning());
mvHandlerInfo.getCreatequery().delete("createQueryInfer");
StatementCompiler.compileStatementAndUpdateCatalog(m_compiler, m_hsql, db, estimates, createQuery, xmlquery, createQuery.getSqltext(), // no user-supplied join order
null, DeterminismMode.FASTER, StatementPartitioning.forceSP());
}
use of org.voltdb.catalog.Statement in project voltdb by VoltDB.
the class TestFragmentProgressUpdate method testPeakLargerThanCurr.
@SuppressWarnings("deprecation")
public void testPeakLargerThanCurr() throws Exception {
m_ee.loadCatalog(0, m_catalog.serialize());
int tableSize = 20000;
int longOpthreshold = 10000;
m_warehousedata.clearRowData();
for (int i = 0; i < tableSize; ++i) {
m_warehousedata.addRow(i, "name" + i, "st1", "st2", "city", "ST", "zip", 0, 0);
}
m_ee.loadTable(WAREHOUSE_TABLEID, m_warehousedata, 0, 0, 0, 0, false, false, WRITE_TOKEN);
assertEquals(tableSize, m_ee.serializeTable(WAREHOUSE_TABLEID).getRowCount());
System.out.println("Rows loaded to table " + m_ee.serializeTable(WAREHOUSE_TABLEID).getRowCount());
Statement selectStmt = m_testProc.getStatements().getIgnoreCase("warehouse_join");
PlanFragment selectBottomFrag = null;
// delete 5000 records
// I have no idea what's going on here, and just copy code from the above methods
int i = 0;
// this kinda assumes the right order
for (PlanFragment f : selectStmt.getFragments()) {
if (i != 0)
selectBottomFrag = f;
i++;
}
// populate plan cache
ActivePlanRepository.clear();
ActivePlanRepository.addFragmentForTest(CatalogUtil.getUniqueIdForFragment(selectBottomFrag), Encoder.decodeBase64AndDecompressToBytes(selectBottomFrag.getPlannodetree()), selectStmt.getSqltext());
ParameterSet params = ParameterSet.emptyParameterSet();
m_ee.executePlanFragments(1, new long[] { CatalogUtil.getUniqueIdForFragment(selectBottomFrag) }, null, new ParameterSet[] { params }, null, new String[] { selectStmt.getSqltext() }, null, null, 3, 3, 2, 42, READ_ONLY_TOKEN, false);
// If want to see the stats, please uncomment the following line.
// It is '8 393216 262144' on my machine.
//System.out.println(m_ee.m_callsFromEE +" " + m_ee.m_peakMemoryInBytes + " "+ m_ee.m_currMemoryInBytes);
assertEquals(longOpthreshold * m_ee.m_callsFromEE, m_ee.m_lastTuplesAccessed);
assertTrue(m_ee.m_peakMemoryInBytes > m_ee.m_currMemoryInBytes);
}
use of org.voltdb.catalog.Statement in project voltdb by VoltDB.
the class TestFragmentProgressUpdate method testFragmentProgressUpdate.
@SuppressWarnings("deprecation")
public void testFragmentProgressUpdate() throws Exception {
m_ee.loadCatalog(0, m_catalog.serialize());
int tableSize = 5001;
int longOpthreshold = 10000;
m_warehousedata.clearRowData();
for (int i = 0; i < tableSize; ++i) {
m_warehousedata.addRow(i, "name" + i, "st1", "st2", "city", "ST", "zip", 0, 0);
}
m_ee.loadTable(WAREHOUSE_TABLEID, m_warehousedata, 0, 0, 0, 0, false, false, WRITE_TOKEN);
assertEquals(tableSize, m_ee.serializeTable(WAREHOUSE_TABLEID).getRowCount());
System.out.println("Rows loaded to table " + m_ee.serializeTable(WAREHOUSE_TABLEID).getRowCount());
Statement selectStmt = m_testProc.getStatements().getIgnoreCase("warehouse_select");
PlanFragment selectBottomFrag = null;
int i = 0;
// this kinda assumes the right order
for (PlanFragment f : selectStmt.getFragments()) {
if (i != 0)
selectBottomFrag = f;
i++;
}
// populate plan cache
ActivePlanRepository.clear();
ActivePlanRepository.addFragmentForTest(CatalogUtil.getUniqueIdForFragment(selectBottomFrag), Encoder.decodeBase64AndDecompressToBytes(selectBottomFrag.getPlannodetree()), selectStmt.getSqltext());
ParameterSet params = ParameterSet.emptyParameterSet();
m_ee.executePlanFragments(1, new long[] { CatalogUtil.getUniqueIdForFragment(selectBottomFrag) }, null, new ParameterSet[] { params }, null, new String[] { selectStmt.getSqltext() }, null, null, 3, 3, 2, 42, Long.MAX_VALUE, false);
// Like many fully successful operations, a single row fetch counts as 2 logical row operations,
// one for locating the row and one for retrieving it.
assertEquals(1, m_ee.m_callsFromEE);
assertEquals(longOpthreshold, m_ee.m_lastTuplesAccessed);
assertTrue(450000 < m_ee.m_currMemoryInBytes);
assertTrue(550000 > m_ee.m_currMemoryInBytes);
assertTrue(450000 < m_ee.m_peakMemoryInBytes);
assertTrue(550000 > m_ee.m_peakMemoryInBytes);
assertTrue(m_ee.m_peakMemoryInBytes >= m_ee.m_currMemoryInBytes);
}
use of org.voltdb.catalog.Statement in project voltdb by VoltDB.
the class ExplainProc method run.
public CompletableFuture<ClientResponse> run(String procedureNames) {
// Go to the catalog and fetch all the "explain plan" strings of the queries in the procedure.
CatalogContext context = VoltDB.instance().getCatalogContext();
/*
* TODO: We don't actually support multiple proc names in an ExplainProc call,
* so I THINK that the string is always a single procname symbol and all this
* splitting and iterating is a no-op.
*/
List<String> procNames = SQLLexer.splitStatements(procedureNames);
int size = procNames.size();
VoltTable[] vt = new VoltTable[size];
for (int i = 0; i < size; i++) {
String procName = procNames.get(i);
// look in the catalog
Procedure proc = context.procedures.get(procName);
if (proc == null) {
// check default procs and send them off to be explained using the regular
// adhoc explain process
proc = context.m_defaultProcs.checkForDefaultProcedure(procName);
if (proc != null) {
String sql = DefaultProcedureManager.sqlForDefaultProc(proc);
List<String> sqlStatements = new ArrayList<>(1);
sqlStatements.add(sql);
return runNonDDLAdHoc(context, sqlStatements, true, null, ExplainMode.EXPLAIN_DEFAULT_PROC, false, new Object[0]);
}
return makeQuickResponse(ClientResponse.GRACEFUL_FAILURE, "Procedure " + procName + " not in catalog");
}
vt[i] = new VoltTable(new VoltTable.ColumnInfo("SQL_STATEMENT", VoltType.STRING), new VoltTable.ColumnInfo("EXECUTION_PLAN", VoltType.STRING));
for (Statement stmt : proc.getStatements()) {
vt[i].addRow(stmt.getSqltext(), Encoder.hexDecodeToString(stmt.getExplainplan()));
}
}
ClientResponseImpl response = new ClientResponseImpl(ClientResponseImpl.SUCCESS, ClientResponse.UNINITIALIZED_APP_STATUS_CODE, null, vt, null);
CompletableFuture<ClientResponse> fut = new CompletableFuture<>();
fut.complete(response);
return fut;
}
Aggregations