use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class PlannerTestAideDeCamp method compile.
/**
* Compile and cache the statement and plan and return the final plan graph.
*/
private List<AbstractPlanNode> compile(String sql, int paramCount, String joinOrder, boolean inferPartitioning, boolean forceSingle, DeterminismMode detMode) {
String stmtLabel = "stmt-" + String.valueOf(compileCounter++);
Statement catalogStmt = proc.getStatements().add(stmtLabel);
catalogStmt.setSqltext(sql);
catalogStmt.setSinglepartition(forceSingle);
// determine the type of the query
QueryType qtype = QueryType.SELECT;
catalogStmt.setReadonly(true);
if (sql.toLowerCase().startsWith("insert")) {
qtype = QueryType.INSERT;
catalogStmt.setReadonly(false);
}
if (sql.toLowerCase().startsWith("update")) {
qtype = QueryType.UPDATE;
catalogStmt.setReadonly(false);
}
if (sql.toLowerCase().startsWith("delete")) {
qtype = QueryType.DELETE;
catalogStmt.setReadonly(false);
}
catalogStmt.setQuerytype(qtype.getValue());
// name will look like "basename-stmt-#"
String name = catalogStmt.getParent().getTypeName() + "-" + catalogStmt.getTypeName();
DatabaseEstimates estimates = new DatabaseEstimates();
TrivialCostModel costModel = new TrivialCostModel();
StatementPartitioning partitioning;
if (inferPartitioning) {
partitioning = StatementPartitioning.inferPartitioning();
} else if (forceSingle) {
partitioning = StatementPartitioning.forceSP();
} else {
partitioning = StatementPartitioning.forceMP();
}
String procName = catalogStmt.getParent().getTypeName();
QueryPlanner planner = new QueryPlanner(sql, stmtLabel, procName, db, partitioning, hsql, estimates, false, StatementCompiler.DEFAULT_MAX_JOIN_TABLES, costModel, null, joinOrder, detMode);
CompiledPlan plan = null;
planner.parse();
plan = planner.plan();
assert (plan != null);
// Partitioning optionally inferred from the planning process.
if (partitioning.isInferred()) {
catalogStmt.setSinglepartition(partitioning.isInferredSingle());
}
// We will need to update the system catalogs with this new information
for (int i = 0; i < plan.parameters.length; ++i) {
StmtParameter catalogParam = catalogStmt.getParameters().add(String.valueOf(i));
ParameterValueExpression pve = plan.parameters[i];
catalogParam.setJavatype(pve.getValueType().getValue());
catalogParam.setIsarray(pve.getParamIsVector());
catalogParam.setIndex(i);
}
List<PlanNodeList> nodeLists = new ArrayList<>();
nodeLists.add(new PlanNodeList(plan.rootPlanGraph));
if (plan.subPlanGraph != null) {
nodeLists.add(new PlanNodeList(plan.subPlanGraph));
}
// Now update our catalog information
// HACK: We're using the node_tree's hashCode() as it's name. It would be really
// nice if the Catalog code give us an guid without needing a name first...
String json = null;
try {
JSONObject jobj = new JSONObject(nodeLists.get(0).toJSONString());
json = jobj.toString(4);
} catch (JSONException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
System.exit(-1);
return null;
}
//
try {
BuildDirectoryUtils.writeFile("statement-plans", name + "_json.txt", json, true);
BuildDirectoryUtils.writeFile("statement-plans", name + ".dot", nodeLists.get(0).toDOTString("name"), true);
} catch (Exception e) {
e.printStackTrace();
}
List<AbstractPlanNode> plannodes = new ArrayList<>();
for (PlanNodeList nodeList : nodeLists) {
plannodes.add(nodeList.getRootPlanNode());
}
m_currentPlan = plan;
return plannodes;
}
use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class ParsedSelectStmt method parseOrderColumn.
private void parseOrderColumn(VoltXMLElement orderByNode, final boolean isDistributed) {
// Aggregation list needs to be cleared before parsing the order by expression
m_aggregationList.clear();
ParsedColInfo.ExpressionAdjuster adjuster = new ParsedColInfo.ExpressionAdjuster() {
@Override
public AbstractExpression adjust(AbstractExpression expr) {
if (isDistributed) {
expr = expr.replaceAVG();
updateAvgExpressions();
}
ExpressionUtil.finalizeValueTypes(expr);
return expr;
}
};
ParsedColInfo order_col = ParsedColInfo.fromOrderByXml(this, orderByNode, adjuster);
AbstractExpression order_exp = order_col.expression;
assert (order_exp != null);
// guards against subquery inside of order by clause
if (order_exp.hasSubquerySubexpression()) {
throw new PlanningErrorException("ORDER BY clauses with subquery expressions are not allowed.");
}
// (for determinism).
for (ParsedColInfo col : m_displayColumns) {
if (col.alias.equals(order_col.alias) || col.expression.equals(order_exp)) {
col.orderBy = true;
col.ascending = order_col.ascending;
order_col.alias = col.alias;
order_col.columnName = col.columnName;
order_col.tableName = col.tableName;
break;
}
}
assert (!(order_exp instanceof ConstantValueExpression));
assert (!(order_exp instanceof ParameterValueExpression));
insertAggExpressionsToAggResultColumns(m_aggregationList, order_col);
if (m_aggregationList.size() >= 1) {
m_hasAggregateExpression = true;
}
// Add TVEs in ORDER BY statement if we have,
// stop recursive finding when we have it in AggResultColumns
List<TupleValueExpression> tveList = new ArrayList<>();
findAllTVEs(order_col.expression, tveList);
insertTVEsToAggResultColumns(tveList);
m_orderColumns.add(order_col);
}
use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class PlanAssembler method canPushDownDistinctAggregation.
private boolean canPushDownDistinctAggregation(AggregateExpression aggExpr) {
assert (m_parsedSelect != null);
assert (aggExpr != null);
assert (aggExpr.isDistinct());
if (aggExpr.getExpressionType() == ExpressionType.AGGREGATE_COUNT_STAR) {
return true;
}
AbstractExpression aggArg = aggExpr.getLeft();
// constant
if (aggArg instanceof ConstantValueExpression || aggArg instanceof ParameterValueExpression) {
return true;
}
if (!(aggArg instanceof TupleValueExpression)) {
return false;
}
TupleValueExpression tve = (TupleValueExpression) aggArg;
String tableAlias = tve.getTableAlias();
StmtTableScan scanTable = m_parsedSelect.getStmtTableScanByAlias(tableAlias);
// table alias may be from AbstractParsedStmt.TEMP_TABLE_NAME.
if (scanTable == null || scanTable.getPartitioningColumns() == null) {
return false;
}
for (SchemaColumn pcol : scanTable.getPartitioningColumns()) {
if (pcol != null && pcol.getColumnName().equals(tve.getColumnName())) {
return true;
}
}
return false;
}
use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class ProcedureCompiler method compileJavaProcedure.
static void compileJavaProcedure(VoltCompiler compiler, HSQLInterface hsql, DatabaseEstimates estimates, Database db, ProcedureDescriptor procedureDescriptor, InMemoryJarfile jarOutput) throws VoltCompiler.VoltCompilerException {
final String className = procedureDescriptor.m_className;
// Load the class given the class name
Class<?> procClass = procedureDescriptor.m_class;
// get the short name of the class (no package)
String shortName = deriveShortProcedureName(className);
// add an entry to the catalog
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(true);
ProcedureAnnotation pa = (ProcedureAnnotation) procedure.getAnnotation();
if (pa == null) {
pa = new ProcedureAnnotation();
procedure.setAnnotation(pa);
}
// get the annotation
// first try to get one that has been passed from the compiler
ProcInfoData info = compiler.getProcInfoOverride(shortName);
// check if partition info was set in ddl
ProcInfoData ddlInfo = null;
if (procedureDescriptor.m_partitionString != null && !procedureDescriptor.m_partitionString.trim().isEmpty()) {
ddlInfo = new ProcInfoData();
ddlInfo.partitionInfo = procedureDescriptor.m_partitionString;
ddlInfo.singlePartition = true;
}
// and create a ProcInfo.Data instance for it
if (info == null) {
info = new ProcInfoData();
ProcInfo annotationInfo = procClass.getAnnotation(ProcInfo.class);
// error out if partition info is present in both ddl and annotation
if (annotationInfo != null) {
if (ddlInfo != null) {
String msg = "Procedure: " + shortName + " has partition properties defined both in ";
msg += "class \"" + className + "\" and in the schema definition file(s)";
throw compiler.new VoltCompilerException(msg);
}
// Prevent AutoGenerated DDL from including PARTITION PROCEDURE for this procedure.
pa.classAnnotated = true;
info.partitionInfo = annotationInfo.partitionInfo();
info.singlePartition = annotationInfo.singlePartition();
} else if (ddlInfo != null) {
info = ddlInfo;
}
} else {
pa.classAnnotated = true;
}
assert (info != null);
// make sure multi-partition implies no partitioning info
if (info.singlePartition == false) {
if ((info.partitionInfo != null) && (info.partitionInfo.length() > 0)) {
String msg = "Procedure: " + shortName + " is annotated as multi-partition";
msg += " but partitionInfo has non-empty value: \"" + info.partitionInfo + "\"";
throw compiler.new VoltCompilerException(msg);
}
}
// if the procedure is non-transactional, then take this special path here
if (VoltNonTransactionalProcedure.class.isAssignableFrom(procClass)) {
compileNTProcedure(compiler, procClass, procedure, jarOutput);
return;
}
// if still here, that means the procedure is transactional
procedure.setTransactional(true);
// track if there are any writer statements and/or sequential scans and/or an overlooked common partitioning parameter
boolean procHasWriteStmts = false;
boolean procHasSeqScans = false;
// procWantsCommonPartitioning == true but commonPartitionExpression == null signifies a proc
// for which the planner was requested to attempt to find an SP plan, but that was not possible
// -- it had a replicated write or it had one or more partitioned reads that were not all
// filtered by the same partition key value -- so it was planned as an MP proc.
boolean procWantsCommonPartitioning = true;
AbstractExpression commonPartitionExpression = null;
String exampleSPstatement = null;
Object exampleSPvalue = null;
// iterate through the fields and get valid sql statements
VoltProcedure procInstance;
try {
procInstance = (VoltProcedure) procClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Error instantiating procedure \"%s\"" + procClass.getName(), e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Error instantiating procedure \"%s\"" + procClass.getName(), e);
}
Map<String, SQLStmt> stmtMap = getValidSQLStmts(compiler, procClass.getSimpleName(), procClass, procInstance, true);
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.putAll(stmtMap);
// find the run() method and get the params
Method procMethod = null;
Method[] methods = procClass.getDeclaredMethods();
for (final Method m : methods) {
String name = m.getName();
if (name.equals("run")) {
assert (m.getDeclaringClass() == procClass);
// if not null, then we've got more than one run method
if (procMethod != null) {
String msg = "Procedure: " + shortName + " has multiple public run(...) methods. ";
msg += "Only a single run(...) method is supported.";
throw compiler.new VoltCompilerException(msg);
}
if (Modifier.isPublic(m.getModifiers())) {
// found it!
procMethod = m;
} else {
compiler.addWarn("Procedure: " + shortName + " has non-public run(...) method.");
}
}
}
if (procMethod == null) {
String msg = "Procedure: " + shortName + " has no run(...) method.";
throw compiler.new VoltCompilerException(msg);
}
// check the return type of the run method
if ((procMethod.getReturnType() != VoltTable[].class) && (procMethod.getReturnType() != VoltTable.class) && (procMethod.getReturnType() != long.class) && (procMethod.getReturnType() != Long.class)) {
String msg = "Procedure: " + shortName + " has run(...) method that doesn't return long, Long, VoltTable or VoltTable[].";
throw compiler.new VoltCompilerException(msg);
}
builder.put("@run", procMethod);
Map<String, Object> fields = builder.build();
// determine if proc is read or read-write by checking if the proc contains any write sql stmts
boolean readWrite = false;
for (Object field : fields.values()) {
if (!(field instanceof SQLStmt))
continue;
SQLStmt stmt = (SQLStmt) field;
QueryType qtype = QueryType.getFromSQL(stmt.getText());
if (!qtype.isReadOnly()) {
readWrite = true;
break;
}
}
// default to FASTER determinism mode, which may favor non-deterministic plans
// but if it's a read-write proc, use a SAFER planning mode wrt determinism.
final DeterminismMode detMode = readWrite ? DeterminismMode.SAFER : DeterminismMode.FASTER;
for (Entry<String, Object> entry : fields.entrySet()) {
if (!(entry.getValue() instanceof SQLStmt))
continue;
String stmtName = entry.getKey();
SQLStmt stmt = (SQLStmt) entry.getValue();
// add the statement to the catalog
Statement catalogStmt = procedure.getStatements().add(stmtName);
// compile the statement
StatementPartitioning partitioning = info.singlePartition ? StatementPartitioning.forceSP() : StatementPartitioning.forceMP();
boolean cacheHit = StatementCompiler.compileFromSqlTextAndUpdateCatalog(compiler, hsql, db, estimates, catalogStmt, stmt.getText(), stmt.getJoinOrder(), detMode, partitioning);
// if this was a cache hit or specified single, don't worry about figuring out more partitioning
if (partitioning.wasSpecifiedAsSingle() || cacheHit) {
// Don't try to infer what's already been asserted.
procWantsCommonPartitioning = false;
// The planner does not currently attempt to second-guess a plan declared as single-partition, 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 constant (expression?) it might display an informational
// message that the passed parameter is assumed to be equal to the hard-coded partition key constant (expression).
// Validate any inferred statement partitioning given the statement's possible usage, until a contradiction is found.
} else if (procWantsCommonPartitioning) {
// conflict with the partitioning of prior statements.
if (partitioning.getCountOfIndependentlyPartitionedTables() == 1) {
AbstractExpression statementPartitionExpression = partitioning.singlePartitioningExpressionForReport();
if (statementPartitionExpression != null) {
if (commonPartitionExpression == null) {
commonPartitionExpression = statementPartitionExpression;
exampleSPstatement = stmt.getText();
exampleSPvalue = partitioning.getInferredPartitioningValue();
} else if (commonPartitionExpression.equals(statementPartitionExpression) || (statementPartitionExpression instanceof ParameterValueExpression && commonPartitionExpression instanceof ParameterValueExpression)) {
// Any constant used for partitioning would have to be the same for all statements, but
// any statement parameter used for partitioning MIGHT come from the same proc parameter as
// any other statement's parameter used for partitioning.
} else {
// appears to be different partitioning for different statements
procWantsCommonPartitioning = false;
}
} else {
// There is a statement with a partitioned table whose partitioning column is
// not equality filtered with a constant or param. Abandon all hope.
procWantsCommonPartitioning = false;
}
// Usually, replicated-only statements in a mix with others have no effect on the MP/SP decision
} else if (partitioning.getCountOfPartitionedTables() == 0) {
// but SP is strictly forbidden for DML, to maintain the consistency of the replicated data.
if (partitioning.getIsReplicatedTableDML()) {
procWantsCommonPartitioning = false;
}
} else {
// There is a statement with a partitioned table whose partitioning column is
// not equality filtered with a constant or param. Abandon all hope.
procWantsCommonPartitioning = false;
}
}
// if a single stmt is not read only, then the proc is not read only
if (catalogStmt.getReadonly() == false) {
procHasWriteStmts = true;
}
if (catalogStmt.getSeqscancount() > 0) {
procHasSeqScans = true;
}
}
// MIGHT the planner have uncovered an overlooked opportunity to run all statements SP?
if (procWantsCommonPartitioning && (commonPartitionExpression != null)) {
String msg = null;
if (commonPartitionExpression instanceof ParameterValueExpression) {
msg = "This procedure might benefit from an @ProcInfo annotation designating parameter " + ((ParameterValueExpression) commonPartitionExpression).getParameterIndex() + " of statement '" + exampleSPstatement + "'";
} else {
String valueDescription = null;
if (exampleSPvalue == null) {
// Statements partitioned on a runtime constant. This is likely to be cryptic, but hopefully gets the idea across.
valueDescription = "of " + commonPartitionExpression.explain("");
} else {
// A simple constant value COULD have been a parameter.
valueDescription = exampleSPvalue.toString();
}
msg = "This procedure might benefit from an @ProcInfo annotation referencing an added parameter passed the value " + valueDescription;
}
compiler.addInfo(msg);
}
// set the read onlyness of a proc
procedure.setReadonly(procHasWriteStmts == false);
procedure.setHasseqscans(procHasSeqScans);
checkForDeterminismWarnings(compiler, shortName, procedure, procHasWriteStmts);
// set procedure parameter types
CatalogMap<ProcParameter> params = procedure.getParameters();
Class<?>[] paramTypes = procMethod.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
Class<?> cls = paramTypes[i];
ProcParameter param = params.add(String.valueOf(i));
param.setIndex(i);
// handle the case where the param is an array
if (cls.isArray()) {
param.setIsarray(true);
cls = cls.getComponentType();
} else
param.setIsarray(false);
// boxed types are not supported parameters at this time
if ((cls == Long.class) || (cls == Integer.class) || (cls == Short.class) || (cls == Byte.class) || (cls == Double.class) || (cls == Character.class) || (cls == Boolean.class)) {
String msg = "Procedure: " + shortName + " has a parameter with a boxed type: ";
msg += cls.getSimpleName();
msg += ". Replace this parameter with the corresponding primitive type and the procedure may compile.";
throw compiler.new VoltCompilerException(msg);
} else if ((cls == Float.class) || (cls == float.class)) {
String msg = "Procedure: " + shortName + " has a parameter with type: ";
msg += cls.getSimpleName();
msg += ". Replace this parameter type with double and the procedure may compile.";
throw compiler.new VoltCompilerException(msg);
}
VoltType type;
try {
type = VoltType.typeFromClass(cls);
} catch (VoltTypeException e) {
// handle the case where the type is invalid
String msg = "Procedure: " + shortName + " has a parameter with invalid type: ";
msg += cls.getSimpleName();
throw compiler.new VoltCompilerException(msg);
} catch (RuntimeException e) {
String msg = "Procedure: " + shortName + " unexpectedly failed a check on a parameter of type: ";
msg += cls.getSimpleName();
msg += " with error: ";
msg += e.toString();
throw compiler.new VoltCompilerException(msg);
}
param.setType(type.getValue());
}
// parse the procinfo
procedure.setSinglepartition(info.singlePartition);
if (info.singlePartition) {
parsePartitionInfo(compiler, db, procedure, info.partitionInfo);
if (procedure.getPartitionparameter() >= paramTypes.length) {
String msg = "PartitionInfo parameter not a valid parameter for procedure: " + procedure.getClassname();
throw compiler.new VoltCompilerException(msg);
}
// check the type of partition parameter meets our high standards
Class<?> partitionType = paramTypes[procedure.getPartitionparameter()];
Class<?>[] validPartitionClzzes = { Long.class, Integer.class, Short.class, Byte.class, long.class, int.class, short.class, byte.class, String.class, byte[].class };
boolean found = false;
for (Class<?> candidate : validPartitionClzzes) {
if (partitionType == candidate)
found = true;
}
if (!found) {
String msg = "PartitionInfo parameter must be a String or Number for procedure: " + procedure.getClassname();
throw compiler.new VoltCompilerException(msg);
}
VoltType columnType = VoltType.get((byte) procedure.getPartitioncolumn().getType());
VoltType paramType = VoltType.typeFromClass(partitionType);
if (!columnType.canExactlyRepresentAnyValueOf(paramType)) {
String msg = "Type mismatch between partition column and partition parameter for procedure " + procedure.getClassname() + " may cause overflow or loss of precision.\nPartition column is type " + columnType + " and partition parameter is type " + paramType;
throw compiler.new VoltCompilerException(msg);
} else if (!paramType.canExactlyRepresentAnyValueOf(columnType)) {
String msg = "Type mismatch between partition column and partition parameter for procedure " + procedure.getClassname() + " does not allow the full range of partition key values.\nPartition column is type " + columnType + " and partition parameter is type " + paramType;
compiler.addWarn(msg);
}
}
// put the compiled code for this procedure into the jarfile
// need to find the outermost ancestor class for the procedure in the event
// that it's actually an inner (or inner inner...) class.
// addClassToJar recursively adds all the children, which should include this
// class
Class<?> ancestor = procClass;
while (ancestor.getEnclosingClass() != null) {
ancestor = ancestor.getEnclosingClass();
}
compiler.addClassToJar(jarOutput, ancestor);
}
use of org.voltdb.expressions.ParameterValueExpression in project voltdb by VoltDB.
the class StatementCompiler method compileDefaultProcedure.
/**
* This procedure compiles a shim org.voltdb.catalog.Procedure representing a default proc.
* The shim has no plan and few details that are expensive to compute.
* The returned proc instance has a full plan and can be used to create a ProcedureRunner.
* Note that while there are two procedure objects here, none are rooted in a real catalog;
* they are entirely parallel to regular, catalog procs.
*
* This code could probably go a few different places. It duplicates a bit too much of the
* StatmentCompiler code for my taste, so I put it here. Next pass could reduce some of the
* duplication?
*/
public static Procedure compileDefaultProcedure(PlannerTool plannerTool, Procedure catProc, String sqlText) {
// fake db makes it easy to create procedures that aren't part of the main catalog
Database fakeDb = new Catalog().getClusters().add("cluster").getDatabases().add("database");
Table table = catProc.getPartitiontable();
// determine the type of the query
QueryType qtype = QueryType.getFromSQL(sqlText);
StatementPartitioning partitioning = catProc.getSinglepartition() ? StatementPartitioning.forceSP() : StatementPartitioning.forceMP();
CompiledPlan plan = plannerTool.planSqlCore(sqlText, partitioning);
Procedure newCatProc = fakeDb.getProcedures().add(catProc.getTypeName());
newCatProc.setClassname(catProc.getClassname());
newCatProc.setDefaultproc(true);
newCatProc.setEverysite(false);
newCatProc.setHasjava(false);
newCatProc.setPartitioncolumn(catProc.getPartitioncolumn());
newCatProc.setPartitionparameter(catProc.getPartitionparameter());
newCatProc.setPartitiontable(catProc.getPartitiontable());
newCatProc.setReadonly(catProc.getReadonly());
newCatProc.setSinglepartition(catProc.getSinglepartition());
newCatProc.setSystemproc(false);
if (catProc.getPartitionparameter() >= 0) {
newCatProc.setAttachment(new ProcedurePartitionInfo(VoltType.get((byte) catProc.getPartitioncolumn().getType()), catProc.getPartitionparameter()));
}
CatalogMap<Statement> statements = newCatProc.getStatements();
assert (statements != null);
Statement stmt = statements.add(VoltDB.ANON_STMT_NAME);
stmt.setSqltext(sqlText);
stmt.setReadonly(catProc.getReadonly());
stmt.setQuerytype(qtype.getValue());
stmt.setSinglepartition(catProc.getSinglepartition());
stmt.setIscontentdeterministic(true);
stmt.setIsorderdeterministic(true);
stmt.setNondeterminismdetail("NO CONTENT FOR DEFAULT PROCS");
stmt.setSeqscancount(plan.countSeqScans());
stmt.setReplicatedtabledml(!catProc.getReadonly() && table.getIsreplicated());
// We will need to update the system catalogs with this new information
for (int i = 0; i < plan.parameters.length; ++i) {
StmtParameter catalogParam = stmt.getParameters().add(String.valueOf(i));
catalogParam.setIndex(i);
ParameterValueExpression pve = plan.parameters[i];
catalogParam.setJavatype(pve.getValueType().getValue());
catalogParam.setIsarray(pve.getParamIsVector());
}
PlanFragment frag = stmt.getFragments().add("0");
// compute a hash of the plan
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
assert (false);
// should never happen with healthy jvm
System.exit(-1);
}
byte[] planBytes = writePlanBytes(frag, plan.rootPlanGraph);
md.update(planBytes, 0, planBytes.length);
// compute the 40 bytes of hex from the 20 byte sha1 hash of the plans
md.reset();
md.update(planBytes);
frag.setPlanhash(Encoder.hexEncode(md.digest()));
if (plan.subPlanGraph != null) {
frag.setHasdependencies(true);
frag.setNontransactional(true);
frag.setMultipartition(true);
frag = stmt.getFragments().add("1");
frag.setHasdependencies(false);
frag.setNontransactional(false);
frag.setMultipartition(true);
byte[] subBytes = writePlanBytes(frag, plan.subPlanGraph);
// compute the 40 bytes of hex from the 20 byte sha1 hash of the plans
md.reset();
md.update(subBytes);
frag.setPlanhash(Encoder.hexEncode(md.digest()));
} else {
frag.setHasdependencies(false);
frag.setNontransactional(false);
frag.setMultipartition(false);
}
// set the procedure parameter types from the statement parameter types
int paramCount = 0;
for (StmtParameter stmtParam : CatalogUtil.getSortedCatalogItems(stmt.getParameters(), "index")) {
// name each parameter "param1", "param2", etc...
ProcParameter procParam = newCatProc.getParameters().add("param" + String.valueOf(paramCount));
procParam.setIndex(stmtParam.getIndex());
procParam.setIsarray(stmtParam.getIsarray());
procParam.setType(stmtParam.getJavatype());
paramCount++;
}
return newCatProc;
}
Aggregations