📄 methodcallnode.java
字号:
/* bug 4450 - if the callable statement is ? = call form, generate the metadata infor for the return parameter. We don't really need that info in order to execute the callable statement. But with jdbc3.0, this information should be made available for return parameter through ParameterMetaData class. Parser sets a flag in compilercontext if ? = call. If the flag is set, we generate the metadata info for the return parameter and reset the flag in the compilercontext for future call statements*/ DataTypeDescriptor dts = DataTypeDescriptor.getSQLDataTypeDescriptor(typeName); if (getCompilerContext().getReturnParameterFlag()) { getCompilerContext().getParameterTypes()[0] = dts; } } /** * Parse the user supplied signature for a method and validate * it, need to match the number of parameters passed in and match * the valid types for the parameter. * @param signature complete external name with signature * @param offset Character offset of first paren * @param hasDynamicResultSets Can ResultSet[] parameters be specified. * @return The valid array of types for resolution. * @throws StandardException */ private String[] parseValidateSignature(String externalName, int offset, boolean hasDynamicResultSets) throws StandardException { int siglen = externalName.length(); // Ensure the opening paren is not the last // character and that the last character is a close paren if (((offset + 1) == siglen) || (externalName.charAt(siglen - 1) != ')')) throw StandardException.newException(SQLState.SQLJ_SIGNATURE_INVALID); // invalid StringTokenizer st = new StringTokenizer(externalName.substring(offset + 1, siglen - 1), ",", true); String[] signatureTypes = new String[signature.length]; int count; boolean seenClass = false; for (count = 0; st.hasMoreTokens();) { String type = st.nextToken().trim(); // check sequence is <class><comma>class> etc. if (",".equals(type)) { if (!seenClass) throw StandardException.newException(SQLState.SQLJ_SIGNATURE_INVALID); // invalid seenClass = false; continue; } else { if (type.length() == 0) throw StandardException.newException(SQLState.SQLJ_SIGNATURE_INVALID); // invalid seenClass = true; count++; } if (count > signature.length) { if (hasDynamicResultSets) { // Allow any number of dynamic result set holders // but they must match the exact type. String rsType = signature[signature.length - 1].getSQLType(). getTypeId().getCorrespondingJavaTypeName(); if (!type.equals(rsType)) throw StandardException.newException(SQLState.LANG_DATA_TYPE_GET_MISMATCH, type, rsType); if (signatureTypes.length == signature.length) { // expand once String[] sigs = new String[st.countTokens()]; System.arraycopy(signatureTypes, 0, sigs, 0, signatureTypes.length); signatureTypes = sigs; } signatureTypes[count - 1] = type; continue; } throw StandardException.newException(SQLState.SQLJ_SIGNATURE_PARAMETER_COUNT, Integer.toString(count), Integer.toString(signature.length)); // too many types } TypeId paramTypeId = signature[count - 1].getSQLType().getTypeId(); // Does it match the object name if (type.equals(paramTypeId.getCorrespondingJavaTypeName())) { signatureTypes[count - 1] = type; continue; } // how about the primitive name if ((paramTypeId.isNumericTypeId() && !paramTypeId.isDecimalTypeId()) || paramTypeId.isBooleanTypeId()) { TypeCompiler tc = getTypeCompiler(paramTypeId); if (type.equals(tc.getCorrespondingPrimitiveTypeName())) { signatureTypes[count - 1] = type; continue; } } throw StandardException.newException(SQLState.LANG_DATA_TYPE_GET_MISMATCH, type, paramTypeId.getSQLTypeName()); // type conversion error } // Did signature end with trailing comma? if (count != 0 && !seenClass) throw StandardException.newException(SQLState.SQLJ_SIGNATURE_INVALID); // invalid if (count < signatureTypes.length) { if (hasDynamicResultSets) { // we can tolerate a count of one less than the // expected count, which means the procedure is declared // to have dynamic result sets, but the explict signature // doesn't have any ResultSet[] types. // So accept, and procedure will automatically have 0 // dynamic results at runtime if (count == (signature.length - 1)) { String[] sigs = new String[count]; System.arraycopy(signatureTypes, 0, sigs, 0, count); return sigs; } } throw StandardException.newException(SQLState.SQLJ_SIGNATURE_PARAMETER_COUNT, Integer.toString(count), Integer.toString(signature.length)); // too few types } return signatureTypes; } /** * Return true if some parameters are null, false otherwise. */ protected boolean someParametersAreNull() { int count = signature.length; for ( int ictr = 0; ictr < count; ictr++ ) { if ( signature[ictr] == null ) { return true; } } return false; } /** * Build an array of names of the argument types. These types are biased toward * Java objects. That is, if an argument is of SQLType, then we map it to the * corresponding Java synonym class (e.g., SQLINT is mapped to 'java.lang.Integer'). * * * @return array of type names * * @exception StandardException Thrown on error */ protected String[] getObjectSignature( ) throws StandardException { int count = signature.length; String parmTypeNames[] = new String[ count ]; for ( int i = 0; i < count; i++ ) { parmTypeNames[i] = getObjectTypeName( signature[ i ] ); } return parmTypeNames; } /** * Build an array of booleans denoting whether or not a given method * parameter is a ?. * * @return array of booleans denoting wheter or not a given method * parameter is a ?. */ protected boolean[] getIsParam() { if (methodParms == null) { return new boolean[0]; } boolean[] isParam = new boolean[methodParms.length]; for (int index = 0; index < methodParms.length; index++) { if (methodParms[index] instanceof SQLToJavaValueNode) { SQLToJavaValueNode stjvn = (SQLToJavaValueNode) methodParms[index]; if (stjvn.value.isParameterNode()) { isParam[index] = true; } } } return isParam; } private String getObjectTypeName( JSQLType jsqlType ) throws StandardException { if ( jsqlType != null ) { switch( jsqlType.getCategory() ) { case JSQLType.SQLTYPE: TypeId ctid = mapToTypeID( jsqlType ); if ( ctid == null ) { return null; } else { // DB2 LUW does not support Java object types for SMALLINT, INTEGER, BIGINT, REAL, DOUBLE // and these are the only types that can map to a primitive or an object type according // to SQL part 13. So always map to the primitive type. We can not use the getPrimitiveSignature() // as it (incorrectly but historically always has) maps a DECIMAL to a double. switch (ctid.getJDBCTypeId()) { case java.sql.Types.SMALLINT: case java.sql.Types.INTEGER: case java.sql.Types.BIGINT: case java.sql.Types.REAL: case java.sql.Types.DOUBLE: if (routineInfo != null) { TypeCompiler tc = getTypeCompiler(ctid); return tc.getCorrespondingPrimitiveTypeName(); } // fall through default: return ctid.getCorrespondingJavaTypeName(); } } case JSQLType.JAVA_CLASS: return jsqlType.getJavaClassName(); case JSQLType.JAVA_PRIMITIVE: return JSQLType.primitiveNames[ jsqlType.getPrimitiveKind() ]; default: if (SanityManager.DEBUG) { SanityManager.THROWASSERT( "Unknown JSQLType: " + jsqlType ); } } } return ""; } String[] getPrimitiveSignature( boolean castToPrimitiveAsNecessary ) throws StandardException { int count = signature.length; String[] primParmTypeNames = new String[ count ]; JSQLType jsqlType; for (int i = 0; i < count; i++) { jsqlType = signature[ i ]; if ( jsqlType == null ) { primParmTypeNames[i] = ""; } else { switch( jsqlType.getCategory() ) { case JSQLType.SQLTYPE: if ((procedurePrimitiveArrayType != null) && (i < procedurePrimitiveArrayType.length) && (procedurePrimitiveArrayType[i] != null)) { primParmTypeNames[i] = procedurePrimitiveArrayType[i]; } else { TypeId ctid = mapToTypeID( jsqlType ); if ((ctid.isNumericTypeId() && !ctid.isDecimalTypeId()) || ctid.isBooleanTypeId()) { TypeCompiler tc = getTypeCompiler(ctid); primParmTypeNames[i] = tc.getCorrespondingPrimitiveTypeName(); if ( castToPrimitiveAsNecessary) { methodParms[i].castToPrimitive(true); } } else { primParmTypeNames[i] = ctid.getCorrespondingJavaTypeName(); } } break; case JSQLType.JAVA_CLASS: primParmTypeNames[i] = jsqlType.getJavaClassName(); break; case JSQLType.JAVA_PRIMITIVE: primParmTypeNames[i] = JSQLType.primitiveNames[ jsqlType.getPrimitiveKind() ]; if ( castToPrimitiveAsNecessary) { methodParms[i].castToPrimitive(true); } break; default: if (SanityManager.DEBUG) { SanityManager.THROWASSERT( "Unknown JSQLType: " + jsqlType ); } } // end switch } // end if } // end for return primParmTypeNames; } /** * Return the variant type for the underlying expression. * The variant type can be: * VARIANT - variant within a scan * (non-static field access) * SCAN_INVARIANT - invariant within a scan * (column references from outer tables) * QUERY_INVARIANT - invariant within the life of a query * (constant expressions) * * @return The variant type for the underlying expression. */ protected int getOrderableVariantType() throws StandardException { // beetle 4880. We return the most variant type of the parameters. If no // params then query-invariant. This makes more sense, and we can evaluate // only once per query (good for performance) because method call could be // expensive. And if we push down method qualifier to store, language // can pre-evaluate the method call. This avoids letting store evaluate // the method while holding page latch, causing deadlock. return getVariantTypeOfParams(); } private int getVariantTypeOfParams() throws StandardException { int variance = Qualifier.QUERY_INVARIANT; if (methodParms != null) { for (int parm = 0; parm < methodParms.length; parm++) { if (methodParms[parm] != null) { int paramVariantType = methodParms[parm].getOrderableVariantType(); if (paramVariantType < variance) //return the most variant type variance = paramVariantType; } else { variance = Qualifier.VARIANT; } } } return variance; } ///////////////////////////////////////////////////////////////////// // // ACCESSORS // ///////////////////////////////////////////////////////////////////// /** * Get the method parameters. * * @return The method parameters */ public JavaValueNode[] getMethodParms() { return methodParms; } /** * Accept a visitor, and call v.visit() * on child nodes as necessary. * * @param v the visitor * * @exception StandardException on error */ public Visitable accept(Visitor v) throws StandardException { Visitable returnNode = v.visit(this); if (v.skipChildren(this)) { return returnNode; } for (int parm = 0; !v.stopTraversal() && parm < methodParms.length; parm++) { if (methodParms[parm] != null) { methodParms[parm] = (JavaValueNode)methodParms[parm].accept(v); } } return returnNode; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -