📄 staticmethodcallnode.java
字号:
* @param mb The method the expression will go into * * * @exception StandardException Thrown on error */ public void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException { if (routineInfo != null) { if (!routineInfo.calledOnNullInput() && routineInfo.getParameterCount() != 0) returnsNullOnNullState = acb.newFieldDeclaration(Modifier.PRIVATE, "boolean"); } // reset the parameters are null indicator. if (returnsNullOnNullState != null) { mb.push(false); mb.setField(returnsNullOnNullState); // for the call to the generated method below. mb.pushThis(); } int nargs = generateParameters(acb, mb); LocalField functionEntrySQLAllowed = null; if (routineInfo != null) { short sqlAllowed = routineInfo.getSQLAllowed(); // Before we set up our authorization level, add a check to see if this // method can be called. If the routine is NO SQL or CONTAINS SQL // then there is no need for a check. As follows: // // Current Level = NO_SQL - CALL will be rejected when getting CALL result set // Current Level = anything else - calls to procedures defined as NO_SQL and CONTAINS SQL both allowed. if (sqlAllowed != RoutineAliasInfo.NO_SQL) { int sqlOperation; if (sqlAllowed == RoutineAliasInfo.READS_SQL_DATA) sqlOperation = Authorizer.SQL_SELECT_OP; else if (sqlAllowed == RoutineAliasInfo.MODIFIES_SQL_DATA) sqlOperation = Authorizer.SQL_WRITE_OP; else sqlOperation = Authorizer.SQL_ARBITARY_OP; generateAuthorizeCheck((ActivationClassBuilder) acb, mb, sqlOperation); } int statmentContextReferences = isSystemCode ? 2 : 1; boolean isFunction = routineInfo.getReturnType() != null; if (isFunction) statmentContextReferences++; if (statmentContextReferences != 0) { 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); for (int scc = 1; scc < statmentContextReferences; scc++) mb.dup(); } /** Set the statement context to reflect we are running System procedures, so that we can execute non-standard SQL. */ if (isSystemCode) { mb.callMethod(VMOpcode.INVOKEINTERFACE, null, "setSystemCode", "void", 0); } // for a function we need to fetch the current SQL control // so that we can reset it once the function is complete. // if (isFunction) { functionEntrySQLAllowed = acb.newFieldDeclaration(Modifier.PRIVATE, "short"); mb.callMethod(VMOpcode.INVOKEINTERFACE, null, "getSQLAllowed", "short", 0); mb.setField(functionEntrySQLAllowed); } // Set up the statement context to reflect the // restricted SQL execution allowed by this routine. mb.push(sqlAllowed); mb.push(false); mb.callMethod(VMOpcode.INVOKEINTERFACE, null, "setSQLAllowed", "void", 2); } // add in the ResultSet arrays. if (routineInfo != null) { int compiledResultSets = methodParameterTypes.length - methodParms.length; 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", ClassName.DataValueDescriptor, 3); mb.endStatement(); } } } constructor.endStatement(); mb.endStatement(); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -