📄 callablestatement.java
字号:
return paramNameBuf.toString(); } private boolean callingStoredFunction = false; private ResultSetInternalMethods functionReturnValueResults; private boolean hasOutputParams = false; // private List parameterList; // private Map parameterMap; private ResultSetInternalMethods outputParameterResults; protected boolean outputParamWasNull = false; private int[] parameterIndexToRsIndex; protected CallableStatementParamInfo paramInfo; private CallableStatementParam returnValueParam; /** * Creates a new CallableStatement * * @param conn * the connection creating this statement * @param paramInfo * the SQL to prepare * * @throws SQLException * if an error occurs */ public CallableStatement(ConnectionImpl conn, CallableStatementParamInfo paramInfo) throws SQLException { super(conn, paramInfo.nativeSql, paramInfo.catalogInUse); this.paramInfo = paramInfo; this.callingStoredFunction = this.paramInfo.isFunctionCall; if (this.callingStoredFunction) { this.parameterCount += 1; } this.retrieveGeneratedKeys = true; // not provided for in the JDBC spec } /** * Creates a callable statement instance -- We need to provide factory-style methods * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise * the class verifier complains when it tries to load JDBC4-only interface * classes that are present in JDBC4 method signatures. */ protected static CallableStatement getInstance(ConnectionImpl conn, String sql, String catalog, boolean isFunctionCall) throws SQLException { if (!Util.isJdbc4()) { return new CallableStatement(conn, sql, catalog, isFunctionCall); } return (CallableStatement) Util.handleNewInstance( JDBC_4_CSTMT_4_ARGS_CTOR, new Object[] { conn, sql, catalog, Boolean.valueOf(isFunctionCall) }); } /** * Creates a callable statement instance -- We need to provide factory-style methods * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise * the class verifier complains when it tries to load JDBC4-only interface * classes that are present in JDBC4 method signatures. */ protected static CallableStatement getInstance(ConnectionImpl conn, CallableStatementParamInfo paramInfo) throws SQLException { if (!Util.isJdbc4()) { return new CallableStatement(conn, paramInfo); } return (CallableStatement) Util.handleNewInstance( JDBC_4_CSTMT_2_ARGS_CTOR, new Object[] { conn, paramInfo }); } private int[] placeholderToParameterIndexMap; private void generateParameterMap() throws SQLException { if (this.paramInfo == null) { return; } // if the user specified some parameters as literals, we need to // provide a map from the specified placeholders to the actual // parameter numbers int parameterCountFromMetaData = this.paramInfo.getParameterCount(); // Ignore the first ? if this is a stored function, it doesn't count if (this.callingStoredFunction) { parameterCountFromMetaData--; } if (this.paramInfo != null && this.parameterCount != parameterCountFromMetaData) { this.placeholderToParameterIndexMap = new int[this.parameterCount]; int startPos = this.callingStoredFunction ? StringUtils.indexOfIgnoreCase(this.originalSql, "SELECT") : StringUtils.indexOfIgnoreCase(this.originalSql, "CALL"); if (startPos != -1) { int parenOpenPos = this.originalSql.indexOf('(', startPos + 4); if (parenOpenPos != -1) { int parenClosePos = StringUtils.indexOfIgnoreCaseRespectQuotes(parenOpenPos, this.originalSql, ")", '\'', true); if (parenClosePos != -1) { List parsedParameters = StringUtils.split(this.originalSql.substring(parenOpenPos + 1, parenClosePos), ",", "'\"", "'\"", true); int numParsedParameters = parsedParameters.size(); // sanity check if (numParsedParameters != this.parameterCount) { // bail? } int placeholderCount = 0; for (int i = 0; i < numParsedParameters; i++) { if (((String)parsedParameters.get(i)).equals("?")) { this.placeholderToParameterIndexMap[placeholderCount++] = i; } } } } } } } /** * Creates a new CallableStatement * * @param conn * the connection creating this statement * @param sql * the SQL to prepare * @param catalog * the current catalog * * @throws SQLException * if an error occurs */ public CallableStatement(ConnectionImpl conn, String sql, String catalog, boolean isFunctionCall) throws SQLException { super(conn, sql, catalog); this.callingStoredFunction = isFunctionCall; if (!this.callingStoredFunction) { if (!StringUtils.startsWithIgnoreCaseAndWs(sql, "CALL")) { // not really a stored procedure call fakeParameterTypes(false); } else { determineParameterTypes(); } generateParameterMap(); } else { determineParameterTypes(); generateParameterMap(); this.parameterCount += 1; } this.retrieveGeneratedKeys = true; // not provided for in the JDBC spec } /* * (non-Javadoc) * * @see java.sql.PreparedStatement#addBatch() */ public void addBatch() throws SQLException { setOutParams(); super.addBatch(); } private CallableStatementParam checkIsOutputParam(int paramIndex) throws SQLException { if (this.callingStoredFunction) { if (paramIndex == 1) { if (this.returnValueParam == null) { this.returnValueParam = new CallableStatementParam("", 0, false, true, Types.VARCHAR, "VARCHAR", 0, 0, DatabaseMetaData.attributeNullableUnknown, DatabaseMetaData.procedureColumnReturn); } return this.returnValueParam; } // Move to position in output result set paramIndex--; } checkParameterIndexBounds(paramIndex); int localParamIndex = paramIndex - 1; if (this.placeholderToParameterIndexMap != null) { localParamIndex = this.placeholderToParameterIndexMap[localParamIndex]; } CallableStatementParam paramDescriptor = this.paramInfo .getParameter(localParamIndex); // We don't have reliable metadata in this case, trust // the caller if (this.connection.getNoAccessToProcedureBodies()) { paramDescriptor.isOut = true; paramDescriptor.isIn = true; paramDescriptor.inOutModifier = DatabaseMetaData.procedureColumnInOut; } else if (!paramDescriptor.isOut) { throw SQLError.createSQLException( Messages.getString("CallableStatement.9") + paramIndex //$NON-NLS-1$ + Messages.getString("CallableStatement.10"), //$NON-NLS-1$ SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } this.hasOutputParams = true; return paramDescriptor; } /** * DOCUMENT ME! * * @param paramIndex * * @throws SQLException */ private void checkParameterIndexBounds(int paramIndex) throws SQLException { this.paramInfo.checkBounds(paramIndex); } /** * Checks whether or not this statement is supposed to be providing * streamable result sets...If output parameters are registered, the driver * can not stream the results. * * @throws SQLException * DOCUMENT ME! */ private void checkStreamability() throws SQLException { if (this.hasOutputParams && createStreamingResultSet()) { throw SQLError.createSQLException(Messages.getString("CallableStatement.14"), //$NON-NLS-1$ SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); } } public synchronized void clearParameters() throws SQLException { super.clearParameters(); try { if (this.outputParameterResults != null) { this.outputParameterResults.close(); } } finally { this.outputParameterResults = null; } } /** * Used to fake up some metadata when we don't have access to * SHOW CREATE PROCEDURE or mysql.proc. * * @throws SQLException if we can't build the metadata. */ private void fakeParameterTypes(boolean isReallyProcedure) throws SQLException { Field[] fields = new Field[13]; fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 0); fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 0); fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 0); fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 0); fields[4] = new Field("", "COLUMN_TYPE", Types.CHAR, 0); fields[5] = new Field("", "DATA_TYPE", Types.SMALLINT, 0); fields[6] = new Field("", "TYPE_NAME", Types.CHAR, 0); fields[7] = new Field("", "PRECISION", Types.INTEGER, 0); fields[8] = new Field("", "LENGTH", Types.INTEGER, 0); fields[9] = new Field("", "SCALE", Types.SMALLINT, 0); fields[10] = new Field("", "RADIX", Types.SMALLINT, 0); fields[11] = new Field("", "NULLABLE", Types.SMALLINT, 0); fields[12] = new Field("", "REMARKS", Types.CHAR, 0); String procName = isReallyProcedure ? extractProcedureName() : null; byte[] procNameAsBytes = null; try { procNameAsBytes = procName == null ? null : procName.getBytes("UTF-8"); } catch (UnsupportedEncodingException ueEx) { procNameAsBytes = StringUtils.s2b(procName, this.connection); } ArrayList resultRows = new ArrayList(); for (int i = 0; i < this.parameterCount; i++) { byte[][] row = new byte[13][]; row[0] = null; // PROCEDURE_CAT row[1] = null; // PROCEDURE_SCHEM row[2] = procNameAsBytes; // PROCEDURE/NAME row[3] = StringUtils.s2b(String.valueOf(i), this.connection); // COLUMN_NAME row[4] = StringUtils.s2b(String .valueOf(DatabaseMetaData.procedureColumnIn), this.connection); row[5] = StringUtils.s2b(String.valueOf(Types.VARCHAR), this.connection); // DATA_TYPE row[6] = StringUtils.s2b("VARCHAR", this.connection); // TYPE_NAME row[7] = StringUtils.s2b(Integer.toString(65535), this.connection); // PRECISION row[8] = StringUtils.s2b(Integer.toString(65535), this.connection); // LENGTH row[9] = StringUtils.s2b(Integer.toString(0), this.connection); // SCALE row[10] = StringUtils.s2b(Integer.toString(10), this.connection); // RADIX row[11] = StringUtils.s2b(Integer .toString(DatabaseMetaData.procedureNullableUnknown), this.connection); // nullable row[12] = null; resultRows.add(new ByteArrayRow(row)); } java.sql.ResultSet paramTypesRs = DatabaseMetaData.buildResultSet( fields, resultRows, this.connection); convertGetProcedureColumnsToInternalDescriptors(paramTypesRs); } private void determineParameterTypes() throws SQLException { if (this.connection.getNoAccessToProcedureBodies()) { fakeParameterTypes(true); return; } java.sql.ResultSet paramTypesRs = null; try { String procName = extractProcedureName(); java.sql.DatabaseMetaData dbmd = this.connection.getMetaData(); boolean useCatalog = false; if (procName.indexOf(".") == -1) { useCatalog = true; } paramTypesRs = dbmd.getProcedureColumns(this.connection .versionMeetsMinimum(5, 0, 2) && useCatalog ? this.currentCatalog : null, null, procName, "%"); //$NON-NLS-1$ convertGetProcedureColumnsToInternalDescriptors(paramTypesRs); } finally { SQLException sqlExRethrow = null; if (paramTypesRs != null) { try { paramTypesRs.close(); } catch (SQLException sqlEx) { sqlExRethrow = sqlEx; } paramTypesRs = null; } if (sqlExRethrow != null) { throw sqlExRethrow; } } } private void convertGetProcedureColumnsToInternalDescriptors(java.sql.ResultSet paramTypesRs) throws SQLException { if (!this.connection.isRunningOnJDK13()) { this.paramInfo = new CallableStatementParamInfoJDBC3( paramTypesRs); } else { this.paramInfo = new CallableStatementParamInfo(paramTypesRs); } } /* * (non-Javadoc) * * @see java.sql.PreparedStatement#execute() */ public boolean execute() throws SQLException { boolean returnVal = false; checkClosed(); checkStreamability(); synchronized (this.connection.getMutex()) { setInOutParamsOnServer(); setOutParams(); returnVal = super.execute(); if (this.callingStoredFunction) { this.functionReturnValueResults = this.results; this.functionReturnValueResults.next(); this.results = null; } retrieveOutParams(); } if (!this.callingStoredFunction) { return returnVal; } // Functions can't return results return false; } /* * (non-Javadoc) * * @see java.sql.PreparedStatement#executeQuery() */ public java.sql.ResultSet executeQuery() throws SQLException { checkClosed(); checkStreamability(); java.sql.ResultSet execResults = null; synchronized (this.connection.getMutex()) { setInOutParamsOnServer(); setOutParams(); execResults = super.executeQuery(); retrieveOutParams(); } return execResults; } /* * (non-Javadoc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -