if (compiledResultSets != 0) {
// Add a method that indicates the maxium number of dynamic result sets.
int maxDynamicResults = routineInfo.getMaxDynamicResultSets();
if (maxDynamicResults > 0) {
MethodBuilder gdr = acb.getClassBuilder().newMethodBuilder(Modifier.PUBLIC, "int", "getMaxDynamicResults");
gdr.push(maxDynamicResults);
gdr.methodReturn();
gdr.complete();
}
// add a method to return all the dynamic result sets (unordered)
MethodBuilder gdr = acb.getClassBuilder().newMethodBuilder(Modifier.PUBLIC, "java.sql.ResultSet[][]", "getDynamicResults");
MethodBuilder cons = acb.getConstructor();
// if (procDef.getParameterStyle() == RoutineAliasInfo.PS_JAVA)
{
// PARAMETER STYLE JAVA
LocalField procedureResultSetsHolder = acb.newFieldDeclaration(Modifier.PRIVATE, "java.sql.ResultSet[][]");
// getDynamicResults body
gdr.getField(procedureResultSetsHolder);
// create the holder of all the ResultSet arrays, new java.sql.ResultSet[][compiledResultSets]
cons.pushNewArray("java.sql.ResultSet[]", compiledResultSets);
cons.setField(procedureResultSetsHolder);
// arguments for the dynamic result sets
for (int i = 0; i < compiledResultSets; i++) {
mb.pushNewArray("java.sql.ResultSet", 1);
mb.dup();
mb.getField(procedureResultSetsHolder);
mb.swap();
mb.setArrayElement(i);
}
}
// complete the method that returns the ResultSet[][] to the
gdr.methodReturn();
gdr.complete();
nargs += compiledResultSets;
}
}
String javaReturnType = getJavaTypeName();
MethodBuilder mbnc = null;
MethodBuilder mbcm = mb;
// If any of the parameters are null then
// do not call the method, just return null.
if (returnsNullOnNullState != null)
{
mbnc = acb.newGeneratedFun(javaReturnType, Modifier.PRIVATE, methodParameterTypes);
// add the throws clause for the public static method we are going to call.
Class[] throwsSet = ((java.lang.reflect.Method) method).getExceptionTypes();
for (int te = 0; te < throwsSet.length; te++)
{
mbnc.addThrownException(throwsSet[te].getName());
}
mbnc.getField(returnsNullOnNullState);
mbnc.conditionalIf();
// set up for a null!!
// for objects is easy.
mbnc.pushNull(javaReturnType);
mbnc.startElseCode();
if (!actualMethodReturnType.equals(javaReturnType))
mbnc.pushNewStart(javaReturnType);
// fetch all the arguments
for (int pa = 0; pa < nargs; pa++)
{
mbnc.getParameter(pa);
}
mbcm = mbnc;
}
mbcm.callMethod(VMOpcode.INVOKESTATIC, method.getDeclaringClass().getName(), methodName,
actualMethodReturnType, nargs);
if (returnsNullOnNullState != null)
{
if (!actualMethodReturnType.equals(javaReturnType))
mbnc.pushNewComplete(1);
mbnc.completeConditional();
mbnc.methodReturn();
mbnc.complete();
// now call the wrapper method
mb.callMethod(VMOpcode.INVOKEVIRTUAL, acb.getClassBuilder().getFullName(), mbnc.getName(),
javaReturnType, nargs);
mbnc = null;
}
if (routineInfo != null) {
// reset the SQL allowed setting that we set upon
// entry to the method.
if (functionEntrySQLAllowed != null) {
acb.pushThisAsActivation(mb);
mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
"getLanguageConnectionContext", ClassName.LanguageConnectionContext, 0);
mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
"getStatementContext", "org.apache.derby.iapi.sql.conn.StatementContext", 0);
mb.getField(functionEntrySQLAllowed);
mb.push(true); // override as we are ending the control set by this function all.
mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
"setSQLAllowed", "void", 2);
}
if (outParamArrays != null) {
MethodBuilder constructor = acb.getConstructor();
// constructor - setting up correct paramter type info
acb.pushThisAsActivation(constructor);
constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
"getParameterValueSet", ClassName.ParameterValueSet, 0);
// execute - passing out parameters back.
acb.pushThisAsActivation(mb);
mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
"getParameterValueSet", ClassName.ParameterValueSet, 0);
int[] parameterModes = routineInfo.getParameterModes();
for (int i = 0; i < outParamArrays.length; i++) {
int parameterMode = parameterModes[i];
if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) {
// must be a parameter if it is INOUT or OUT.
ValueNode sqlParamNode = ((SQLToJavaValueNode) methodParms[i]).getSQLValueNode();
int applicationParameterNumber = applicationParameterNumbers[i];
// Set the correct parameter nodes in the ParameterValueSet at constructor time.
constructor.dup();
constructor.push(applicationParameterNumber);
constructor.push(parameterMode);
constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
"setParameterMode", "void", 2);
// Pass the value of the outparameters back to the calling code
LocalField lf = outParamArrays[i];
mb.dup();
mb.push(applicationParameterNumber);
mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
"getParameter", ClassName.DataValueDescriptor, 1);
// see if we need to set the desired length/scale/precision of the type
DataTypeDescriptor paramdtd = sqlParamNode.getTypeServices();
boolean isNumericType = paramdtd.getTypeId().isNumericTypeId();
// is the underlying type for the OUT/INOUT parameter primitive.
boolean isPrimitive = ((java.lang.reflect.Method) method).getParameterTypes()[i].getComponentType().isPrimitive();
if (isNumericType) {
// need to up-cast as the setValue(Number) method only exists on NumberDataValue
if (!isPrimitive)
mb.cast(ClassName.NumberDataValue);
}
else if (paramdtd.getTypeId().isBooleanTypeId())
{
// need to cast as the setValue(Boolean) method only exists on BooleanDataValue
if (!isPrimitive)
mb.cast(ClassName.BooleanDataValue);
}
if (paramdtd.getTypeId().variableLength()) {
// need another DVD reference for the set width below.
mb.dup();
}
mb.getField(lf); // pvs, dvd, array
mb.getArrayElement(0); // pvs, dvd, value
// The value needs to be set thorugh the setValue(Number) method.
if (isNumericType && !isPrimitive)
{
mb.upCast("java.lang.Number");
}
mb.callMethod(VMOpcode.INVOKEINTERFACE, null, "setValue", "void", 1);
if (paramdtd.getTypeId().variableLength()) {
mb.push(isNumericType ? paramdtd.getPrecision() : paramdtd.getMaximumWidth());
mb.push(paramdtd.getScale());
mb.push(isNumericType);
mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", "void", 3);
// mb.endStatement();
}
}
}
constructor.endStatement();
mb.endStatement();
}
}
}