Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ParameterMetaData.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ParameterMetaData.java?rev=165178&view=auto ============================================================================== --- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ParameterMetaData.java (added) +++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ParameterMetaData.java Thu Apr 28 12:05:42 2005 @@ -0,0 +1,146 @@ +/* + + Derby - Class org.apache.derby.client.am.ParameterMetaData + + Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +package org.apache.derby.client.am; + +// Parameter meta data as used internally by the driver is always a column meta data instance. +// We will only create instances of this class when getParameterMetaData() is called. +// This class simply wraps a column meta data instance. +// +// Once we go to JDK 1.4 as runtime pre-req, we can extend ColumnMetaData and new up ParameterMetaData instances directly, +// and we won't have to wrap column meta data instances directly. +public class ParameterMetaData implements java.sql.ParameterMetaData +{ + ColumnMetaData columnMetaData_; + + // This is false unless for parameterMetaData for a call statement with return clause + boolean escapedProcedureCallWithResult_ = false; + + public ParameterMetaData (ColumnMetaData columnMetaData) + { + columnMetaData_ = columnMetaData; + } + + public int getParameterCount () throws SqlException + { + if (escapedProcedureCallWithResult_) + return columnMetaData_.columns_++; + return columnMetaData_.columns_; + } + + public int getParameterType (int param) throws SqlException + { + if (escapedProcedureCallWithResult_) + { + param--; + if (param == 0) + return java.sql.Types.INTEGER; + } + return columnMetaData_.getColumnType (param); + } + + public String getParameterTypeName (int param) throws SqlException + { + if (escapedProcedureCallWithResult_) + { + param--; + if (param == 0) + return "INTEGER"; + } + return columnMetaData_.getColumnTypeName (param); + } + + public String getParameterClassName (int param) throws SqlException + { + if (escapedProcedureCallWithResult_) + { + param--; + if (param == 0) + return "java.lang.Integer"; + } + return columnMetaData_.getColumnClassName (param); + } + + public int getParameterMode (int param) throws SqlException + { + if (escapedProcedureCallWithResult_) + { + param--; + if (param == 0) + return java.sql.ParameterMetaData.parameterModeOut; + } + columnMetaData_.checkForValidColumnIndex (param); + if (columnMetaData_.sqlxParmmode_[param - 1] == java.sql.ParameterMetaData.parameterModeUnknown) + return java.sql.ParameterMetaData.parameterModeUnknown; + else if (columnMetaData_.sqlxParmmode_[param - 1] == java.sql.ParameterMetaData.parameterModeIn) + return java.sql.ParameterMetaData.parameterModeIn; + else if (columnMetaData_.sqlxParmmode_[param - 1] == java.sql.ParameterMetaData.parameterModeOut) + return java.sql.ParameterMetaData.parameterModeOut; + else + return java.sql.ParameterMetaData.parameterModeInOut; + } + + public int isNullable (int param) throws SqlException + { + if (escapedProcedureCallWithResult_) + { + param--; + if (param == 0) + return java.sql.ResultSetMetaData.columnNoNulls; + } + return columnMetaData_.isNullable (param); + } + + public boolean isSigned (int param) throws SqlException + { + if (escapedProcedureCallWithResult_) + { + param--; + if (param == 0) + return true; + } + return columnMetaData_.isSigned (param); + } + + public int getPrecision (int param) throws SqlException + { + if (escapedProcedureCallWithResult_) + { + param--; + if (param == 0) + return 10; + } + return columnMetaData_.getPrecision (param); + } + + public int getScale (int param) throws SqlException + { + if (escapedProcedureCallWithResult_) + { + param--; + if (param == 0) + return 0; + } + return columnMetaData_.getScale (param); + } + +} + +
Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ParameterMetaData.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java?rev=165178&view=auto ============================================================================== --- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java (added) +++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java Thu Apr 28 12:05:42 2005 @@ -0,0 +1,1609 @@ +/* + + Derby - Class org.apache.derby.client.am.PreparedStatement + + Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +package org.apache.derby.client.am; + +import org.apache.derby.client.am.Section; + +public class PreparedStatement extends Statement + implements java.sql.PreparedStatement, + PreparedStatementCallbackInterface +{ + //---------------------navigational cheat-links------------------------------- + // Cheat-links are for convenience only, and are not part of the conceptual model. + // Warning: + // Cheat-links should only be defined for invariant state data. + // That is, the state data is set by the constructor and never changes. + + // Alias for downcast (MaterialPreparedStatementProxy) super.materialStatement. + public MaterialPreparedStatement materialPreparedStatement_ = null; + + //-----------------------------state------------------------------------------ + + public String sql_; + + // This variable is only used by Batch. + // True if a call sql statement has an OUT or INOUT parameter registered. + public boolean outputRegistered_ = false; + + // Parameter inputs are cached as objects so they may be sent on execute() + public Object[] parameters_; + + boolean[] parameterSet_; + boolean[] parameterRegistered_; + + void setInput (int parameterIndex, Object input) + { parameters_[parameterIndex-1] = input; parameterSet_[parameterIndex-1] = true; } + + public ColumnMetaData parameterMetaData_; // type information for input sqlda + + + // The problem with storing the scrollable ResultSet associated with cursorName in scrollableRS_ is + // that when the PreparedStatement is re-executed, it has a new ResultSet, however, we always do + // the reposition on the ResultSet that was stored in scrollableRS_, and we never update scrollableRS_ + // when PreparedStatement is re-execute. So the new ResultSet that needs to be repositioned never + // gets repositioned. + // So instead of caching the scrollableRS_, we will cache the cursorName. And re-retrieve the scrollable + // result set from the map using this cursorName every time the PreparedStatement excutes. + String positionedUpdateCursorName_ = null; + + + private void initPreparedStatement() + { + materialPreparedStatement_ = null; + sql_ = null; + outputRegistered_ = false; + parameters_ = null; + parameterSet_ = null; + parameterRegistered_ = null; + parameterMetaData_ = null; + isAutoCommittableStatement_ = true; + isPreparedStatement_ = true; + } + + protected void initResetPreparedStatement() + { + outputRegistered_ = false; + isPreparedStatement_ = true; + + if (parameterMetaData_ != null) + resetParameters(); + } + + public void reset (boolean fullReset) throws SqlException + { + if (fullReset) + connection_.resetPrepareStatement (this); + else { + super.initResetPreparedStatement(); + initResetPreparedStatement(); + } + } + + private void resetParameters () + { + for (int i = 0; i < parameterMetaData_.columns_; i++) { + parameters_[i] = null; + parameterSet_[i] = false; + parameterRegistered_[i] = false; + } + } + + // For for JDBC 2 positioned update statements. + // Called by material statement constructors. + public PreparedStatement (Agent agent, + Connection connection, + String sql, + Section section) throws SqlException + { + super (agent, connection); + initPreparedStatement (sql, section); + } + + public void resetPreparedStatement (Agent agent, + Connection connection, + String sql, + Section section) throws SqlException + { + super.resetStatement(agent, connection); + initPreparedStatement(); + initPreparedStatement (sql, section); + } + + private void initPreparedStatement (String sql, Section section) throws SqlException + { + sql_ = sql; + isPreparedStatement_ = true; + + parseSqlAndSetSqlModes (sql_); + section_ = section; + } + + // Constructor for jdbc 2 prepared statements with scroll attributes. + // Called by material statement constructors. + public PreparedStatement (Agent agent, + Connection connection, + String sql, + int type, int concurrency, int holdability, int autoGeneratedKeys, String[] columnNames) throws SqlException + { + super (agent, connection, type, concurrency, holdability, autoGeneratedKeys, columnNames); + initPreparedStatement (sql); + } + + public void resetPreparedStatement (Agent agent, + Connection connection, + String sql, + int type, int concurrency, int holdability, int autoGeneratedKeys, String[] columnNames) throws SqlException + { + super.resetStatement(agent, connection, type, concurrency, holdability, autoGeneratedKeys, columnNames); + initPreparedStatement(); + initPreparedStatement (sql); + } + + private void initPreparedStatement ( String sql) throws SqlException + { + sql_ = super.escape (sql); + parseSqlAndSetSqlModes (sql_); + isPreparedStatement_ = true; + + // Check for positioned update statement and assign a section from the + // same package as the corresponding query section. + // Scan the sql for an "update...where current of <cursor-name>". + String cursorName = null; + if(sqlUpdateMode_ == isDeleteSql__ || sqlUpdateMode_ == isUpdateSql__) { + String[] sqlAndCursorName = extractCursorNameFromWhereCurrentOf (sql_); + if(sqlAndCursorName != null) { + cursorName = sqlAndCursorName[0]; + sql_ = sqlAndCursorName[1]; + } + } + if (cursorName != null) { + positionedUpdateCursorName_ = cursorName; + // Get a new section from the same package as the query section + section_ = agent_.sectionManager_.getPositionedUpdateSection (cursorName, false); // false means get a regular section + + if (section_ == null) + throw new SqlException (agent_.logWriter_, "Invalid cursor name \"" + cursorName + "\" in the Update/Delete statement."); + + //scrollableRS_ = agent_.sectionManager_.getPositionedUpdateResultSet (cursorName); + + // if client's cursor name is set, and the cursor name in the positioned update + // string is the same as the client's cursor name, replace client's cursor name + // with the server's cursor name. + // if the cursor name supplied in the sql string is different from the cursorName + // set by setCursorName(), then server will return "cursor name not defined" error, + // and no subsititution is made here. + if (section_.getClientCursorName() != null && // cursor name is user defined + cursorName.compareTo (section_.getClientCursorName()) == 0) + // client's cursor name is substituted with section's server cursor name + sql_ = substituteClientCursorNameWithServerCursorName (sql_, section_); + } + else { + // We don't need to analyze the sql text to determine if it is a query or not. + // This is up to the server to decide, we just pass thru the sql on flowPrepare(). + section_ = agent_.sectionManager_.getDynamicSection (resultSetHoldability_); + } + } + + public void resetPreparedStatement (Agent agent, + Connection connection, + String sql, + Section section, + ColumnMetaData parameterMetaData, + ColumnMetaData resultSetMetaData) throws SqlException + { + resetPreparedStatement (agent, connection, sql, section); + initPreparedStatement (parameterMetaData, resultSetMetaData); + } + + private void initPreparedStatement ( + ColumnMetaData parameterMetaData, + ColumnMetaData resultSetMetaData) throws SqlException + { + isPreparedStatement_ = true; + parameterMetaData_ = parameterMetaData; + resultSetMetaData_ = resultSetMetaData; + if(parameterMetaData_ != null) { + parameters_ = new Object[parameterMetaData_.columns_]; + //parameterSetOrRegistered_ = new boolean[parameterMetaData_.columns_]; + parameterSet_ = new boolean[parameterMetaData_.columns_]; + parameterRegistered_ = new boolean[parameterMetaData_.columns_]; + } + } + + protected void finalize () throws java.lang.Throwable + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "finalize"); + if (openOnClient_) { + synchronized (connection_) { + closeX(); + } + } + super.finalize(); + } + + // called immediately after the constructor by Connection prepare*() methods + void prepare () throws SqlException + { + try { + // flow prepare, no static initialization is needed + // already checked if columnNames is not null and server supports select from insert + // in prepareStatementX() + if (sqlUpdateMode_ == isInsertSql__ && generatedKeysColumnNames_ != null) + flowPrepareForSelectFromInsert (); + else + flowPrepareDescribeInputOutput(); + } + catch (SqlException e) { + this.markClosed(); + throw e; + } + } + + + //------------------- Prohibited overrides from Statement -------------------- + + public boolean execute (String sql) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "execute", sql); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.execute (String sql) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.execute () with no sql string argument."); + } + + public java.sql.ResultSet executeQuery (String sql) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "executeQuery", sql); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.executeQuery (String sql) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.executeQuery () with no sql string argument."); + } + + public int executeUpdate (String sql) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "executeUpdate", sql); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.executeUpdate (String sql) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.executeUpdate () with no sql string argument."); + } + // ---------------------------jdbc 1------------------------------------------ + + public java.sql.ResultSet executeQuery () throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "executeQuery"); + ResultSet resultSet = executeQueryX(); + if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "executeQuery", resultSet); + return resultSet; + } + } + + // also called by some DBMD methods + ResultSet executeQueryX () throws SqlException + { + flowExecute (executeQueryMethod__); + + super.checkExecuteQueryPostConditions ("java.sql.PreparedStatement"); + return resultSet_; + } + + + public int executeUpdate () throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "executeUpdate"); + int updateValue = executeUpdateX(); + if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "executeUpdate", updateValue); + return updateValue; + } + } + + // also used by Blob + int executeUpdateX () throws SqlException + { + flowExecute (executeUpdateMethod__); + + if (sqlMode_ == isUpdate__) super.checkExecuteUpdatePostConditions ("java.sql.PreparedStatement"); + return updateCount_; + } + + public void setNull (int parameterIndex, int jdbcType) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setNull", parameterIndex, jdbcType); + setNullX (parameterIndex, jdbcType); + } + } + + // also used by DBMD methods + void setNullX (int parameterIndex, int jdbcType) throws SqlException + { + super.checkForClosedStatement(); // investigate what can be pushed up to setNull + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = jdbcType; + + if (!parameterMetaData_.nullable_[parameterIndex - 1]) + throw new SqlException (agent_.logWriter_, "PreparedStatement: setNull method setting a non-nullable " + + "input parameter " + parameterIndex + " to null."); + setInput (parameterIndex, null); + } + + public void setNull (int parameterIndex, int jdbcType, String typeName) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setNull", parameterIndex, jdbcType, typeName); + super.checkForClosedStatement(); + setNull (parameterIndex, jdbcType); + } + } + + public void setBoolean (int parameterIndex, boolean x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setBoolean", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.BIT; + setInput(parameterIndex, new Short ((short)(x ? 1 : 0))); + } + } + + public void setByte (int parameterIndex, byte x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setByte", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.TINYINT; + setInput(parameterIndex, new Short (x)); + } + } + + public void setShort (int parameterIndex, short x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setShort", parameterIndex, x); + setShortX (parameterIndex, x); + } + } + + // also used by DBMD methods + void setShortX (int parameterIndex, short x) throws SqlException + { + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.SMALLINT; + setInput(parameterIndex, new Short (x)); + + } + + public void setInt (int parameterIndex, int x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setInt", parameterIndex, x); + setIntX (parameterIndex, x); + } + } + + // also used by DBMD methods + void setIntX (int parameterIndex, int x) throws SqlException + { + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.INTEGER; + setInput(parameterIndex, new Integer (x)); + } + + + public void setLong (int parameterIndex, long x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setLong", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.BIGINT; + setInput(parameterIndex, new Long (x)); + } + } + + public void setFloat (int parameterIndex, float x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setFloat", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.REAL; + setInput(parameterIndex, new Float(x)); + } + } + + public void setDouble (int parameterIndex, double x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setDouble", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.DOUBLE; + setInput(parameterIndex, new Double(x)); + } + } + + public void setBigDecimal (int parameterIndex, java.math.BigDecimal x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setBigDecimal", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.DECIMAL; + if (x == null) { setNull (parameterIndex, java.sql.Types.DECIMAL); return; } + int registerOutScale = 0; + setInput(parameterIndex, x); + } + } + + public void setDate (int parameterIndex, java.sql.Date x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setDate", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.DATE; + if (x == null) { setNull (parameterIndex, java.sql.Types.DATE); return; } + setInput(parameterIndex, x); + } + } + + public void setDate (int parameterIndex, + java.sql.Date x, + java.util.Calendar calendar) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setDate", parameterIndex, x, calendar); + if (calendar == null) throw new SqlException (agent_.logWriter_, "Invalid parameter: calendar is null"); + java.util.Calendar targetCalendar = java.util.Calendar.getInstance(calendar.getTimeZone()); + targetCalendar.clear(); + targetCalendar.setTime(x); + java.util.Calendar defaultCalendar = java.util.Calendar.getInstance(); + defaultCalendar.clear(); + defaultCalendar.setTime(x); + long timeZoneOffset = + targetCalendar.get(java.util.Calendar.ZONE_OFFSET) - defaultCalendar.get(java.util.Calendar.ZONE_OFFSET) + + targetCalendar.get(java.util.Calendar.DST_OFFSET) - defaultCalendar.get(java.util.Calendar.DST_OFFSET); + java.sql.Date adjustedDate = ((timeZoneOffset == 0) || (x==null)) ? x : new java.sql.Date (x.getTime() + timeZoneOffset); + setDate (parameterIndex, adjustedDate); + } + } + + public void setTime (int parameterIndex, java.sql.Time x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setTime", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.TIME; + if (x == null) { setNull (parameterIndex, java.sql.Types.TIME); return; } + setInput(parameterIndex, x); + + } + } + + public void setTime (int parameterIndex, + java.sql.Time x, + java.util.Calendar calendar) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setTime", parameterIndex, x, calendar); + if (calendar == null) throw new SqlException (agent_.logWriter_, "Invalid parameter: calendar is null"); + java.util.Calendar targetCalendar = java.util.Calendar.getInstance(calendar.getTimeZone()); + targetCalendar.clear(); + targetCalendar.setTime(x); + java.util.Calendar defaultCalendar = java.util.Calendar.getInstance(); + defaultCalendar.clear(); + defaultCalendar.setTime(x); + long timeZoneOffset = + targetCalendar.get(java.util.Calendar.ZONE_OFFSET) - defaultCalendar.get(java.util.Calendar.ZONE_OFFSET) + + targetCalendar.get(java.util.Calendar.DST_OFFSET) - defaultCalendar.get(java.util.Calendar.DST_OFFSET); + java.sql.Time adjustedTime = ((timeZoneOffset == 0) || (x==null)) ? x : new java.sql.Time (x.getTime() + timeZoneOffset); + setTime (parameterIndex, adjustedTime); + } + } + + public void setTimestamp (int parameterIndex, java.sql.Timestamp x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setTimestamp", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1 ] = java.sql.Types.TIMESTAMP; + + if (x == null) { setNull (parameterIndex, java.sql.Types.TIMESTAMP); return; } + setInput (parameterIndex, x); + // once the nanosecond field of timestamp is trim to microsecond for DERBY, should we throw a warning + //if (getParameterType (parameterIndex) == java.sql.Types.TIMESTAMP && x.getNanos() % 1000 != 0) + // accumulateWarning (new SqlWarning (agent_.logWriter_, "DERBY timestamp can only store up to microsecond, conversion from nanosecond to microsecond causes rounding.")); + } + } + + public void setTimestamp (int parameterIndex, + java.sql.Timestamp x, + java.util.Calendar calendar) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setTimestamp", parameterIndex, x, calendar); + if (calendar == null) throw new SqlException (agent_.logWriter_, "Invalid parameter: calendar is null"); + java.util.Calendar targetCalendar = java.util.Calendar.getInstance(calendar.getTimeZone()); + targetCalendar.clear(); + targetCalendar.setTime(x); + java.util.Calendar defaultCalendar = java.util.Calendar.getInstance(); + defaultCalendar.clear(); + defaultCalendar.setTime(x); + long timeZoneOffset = + targetCalendar.get(java.util.Calendar.ZONE_OFFSET) - defaultCalendar.get(java.util.Calendar.ZONE_OFFSET) + + targetCalendar.get(java.util.Calendar.DST_OFFSET) - defaultCalendar.get(java.util.Calendar.DST_OFFSET); + java.sql.Timestamp adjustedTimestamp = ((timeZoneOffset == 0) || (x==null)) ? x : new java.sql.Timestamp (x.getTime() + timeZoneOffset); + if (x != null) adjustedTimestamp.setNanos (x.getNanos()); + setTimestamp (parameterIndex, adjustedTimestamp); + } + } + + public void setString (int parameterIndex, String x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setString", parameterIndex, x); + setStringX (parameterIndex, x); + } + } + + // also used by DBMD methods + void setStringX (int parameterIndex, String x) throws SqlException + { + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.LONGVARCHAR; + if (x == null) { setNull (parameterIndex, java.sql.Types.LONGVARCHAR); return; } + setInput(parameterIndex, x); + } + + public void setBytes (int parameterIndex, byte[] x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setBytes", parameterIndex, x); + setBytesX (parameterIndex, x); + } + } + + // also used by BLOB + public void setBytesX (int parameterIndex, byte[] x) throws SqlException + { + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.LONGVARBINARY; + if (x == null) { setNull (parameterIndex, java.sql.Types.LONGVARBINARY); return; } + setInput(parameterIndex, x); + + } + + public void setBinaryStream (int parameterIndex, + java.io.InputStream x, + int length) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setBinaryStream", parameterIndex, "<input stream>", length); + setBinaryStreamX (parameterIndex, x, length); + } + } + + public void setBinaryStreamX (int parameterIndex, + java.io.InputStream x, + int length) throws SqlException + { + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.BLOB; + if (x == null) { setNull (parameterIndex, java.sql.Types.BLOB); return; } + setInput(parameterIndex, new Blob (agent_, x, length)); + } + + public void setAsciiStream (int parameterIndex, + java.io.InputStream x, + int length) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setAsciiStream", parameterIndex, "<input stream>", length); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.CLOB; + if (x == null) { setNull (parameterIndex, java.sql.Types.CLOB); return; } + setInput(parameterIndex, new Clob (agent_, x, "US-ASCII", length)); + } + } + + public void setUnicodeStream (int parameterIndex, + java.io.InputStream x, + int length) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceDeprecatedEntry (this, "setUnicodeStream", parameterIndex, "<input stream>", length); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.CLOB; + if (x == null) { setNull (parameterIndex, java.sql.Types.CLOB); return; } + setInput(parameterIndex, new Clob (agent_, x, "UnicodeBigUnmarked", length)); + } + } + + public void setCharacterStream (int parameterIndex, + java.io.Reader x, + int length) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setCharacterStream", parameterIndex, x, length); + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.CLOB; + if (x == null) { setNull (parameterIndex, java.sql.Types.CLOB); return; } + setInput(parameterIndex, new Clob (agent_, x, length)); + } + } + + public void setBlob (int parameterIndex, java.sql.Blob x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setBlob", parameterIndex, x); + setBlobX (parameterIndex, x); + } + } + + // also used by Blob + public void setBlobX (int parameterIndex, java.sql.Blob x) throws SqlException + { + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.BLOB; + if (x == null) { setNull (parameterIndex, java.sql.Types.BLOB); return; } + setInput(parameterIndex, x); + } + + public void setClob (int parameterIndex, java.sql.Clob x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setClob", parameterIndex, x); + setClobX (parameterIndex, x); + } + } + + // also used by Clob + void setClobX (int parameterIndex, java.sql.Clob x) throws SqlException + { + parameterIndex = checkSetterPreconditions (parameterIndex); + parameterMetaData_.clientParamtertype_[parameterIndex -1] = java.sql.Types.CLOB; + if (x == null) { this.setNullX (parameterIndex, Types.CLOB); return; } + setInput(parameterIndex, x); + } + + + public void setArray (int parameterIndex, java.sql.Array x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setArray", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + throw new SqlException (agent_.logWriter_, "jdbc 2 method not yet implemented"); + } + } + + public void setRef (int parameterIndex, java.sql.Ref x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setRef", parameterIndex, x); + parameterIndex = checkSetterPreconditions (parameterIndex); + throw new SqlException (agent_.logWriter_, "jdbc 2 method not yet implemented"); + } + } + + // The Java compiler uses static binding, so we must use instanceof + // rather than to rely on separate setObject() methods for + // each of the Java Object instance types recognized below. + public void setObject (int parameterIndex, Object x) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setObject", parameterIndex, x); + super.checkForClosedStatement(); + if (x instanceof String) setString (parameterIndex, (String) x); + else if (x instanceof Integer) setInt (parameterIndex, ((Integer) x).intValue()); + else if (x instanceof Double) setDouble (parameterIndex, ((Double) x).doubleValue()); + else if (x instanceof Float) setFloat (parameterIndex, ((Float) x).floatValue()); + else if (x instanceof Boolean) setBoolean (parameterIndex, ((Boolean) x).booleanValue()); + else if (x instanceof Long) setLong (parameterIndex, ((Long) x).longValue()); + else if (x instanceof byte[]) setBytes (parameterIndex, (byte[]) x); + else if (x instanceof java.math.BigDecimal) setBigDecimal (parameterIndex, (java.math.BigDecimal) x); + else if (x instanceof java.sql.Date) setDate (parameterIndex, (java.sql.Date) x); + else if (x instanceof java.sql.Time) setTime (parameterIndex, (java.sql.Time) x); + else if (x instanceof java.sql.Timestamp) setTimestamp (parameterIndex, (java.sql.Timestamp) x); + else if (x instanceof java.sql.Blob) setBlob (parameterIndex, (java.sql.Blob) x); + else if (x instanceof java.sql.Clob) setClob (parameterIndex, (java.sql.Clob) x); + else if (x instanceof java.sql.Array) setArray (parameterIndex, (java.sql.Array) x); + else if (x instanceof java.sql.Ref) setRef (parameterIndex, (java.sql.Ref) x); + else if (x instanceof Short) setShort (parameterIndex, ((Short) x).shortValue()); + else if (x instanceof Byte) setByte (parameterIndex, ((Byte) x).byteValue()); + else { + checkSetterPreconditions (parameterIndex); + throw new SqlException (agent_.logWriter_, "Invalid data conversion:" + + " Parameter object type is invalid for requested conversion."); + } + } + } + + public void setObject (int parameterIndex, Object x, int targetJdbcType) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setObject", parameterIndex, x, targetJdbcType); + setObjectX (parameterIndex, x, targetJdbcType, 0); + } + } + + public void setObject (int parameterIndex, + Object x, + int targetJdbcType, + int scale) throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setObject", parameterIndex, x, targetJdbcType, scale); + setObjectX (parameterIndex, x, targetJdbcType, scale); + } + } + + private void setObjectX (int parameterIndex, + Object x, + int targetJdbcType, + int scale) throws SqlException + { + parameterIndex = checkSetterPreconditions (parameterIndex); + checkForValidScale (scale); + + if (x == null) { setNull (parameterIndex, targetJdbcType); return; } + setObject(parameterIndex, x); + } + + // Since parameters are cached as objects in parameters_[], + // java null may be used to represent SQL null. + public void clearParameters () throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled ()) agent_.logWriter_.traceEntry (this, "clearParameters"); + checkForClosedStatement (); + if (parameterMetaData_ != null) { + for (int i = 0; i < parameters_.length; i++) + parameters_[i] = null; + + for (int i = 0; i < parameterSet_.length; i++) + parameterSet_[i] = false; + } + } + } + + public boolean execute () throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "execute"); + boolean b = executeX(); + if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "execute", b); + return b; + } + } + + private boolean executeX () throws SqlException + { + flowExecute (executeMethod__); + + return resultSet_ != null; + } + + //--------------------------JDBC 2.0----------------------------- + + public void addBatch () throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "addBatch"); + checkForClosedStatement (); + checkThatAllParametersAreSet(); + + // ASSERT: since OUT/INOUT parameters are not allowed, there should + // be no problem in sharing the JDBC Wrapper object instances + // since they will not be modified by the driver. + + // batch up the parameter values -- deep copy req'd + + if(parameterMetaData_ != null) { + Object[] inputsClone = new Object[parameters_.length]; + System.arraycopy (parameters_, 0, inputsClone, 0, parameters_.length); + + batch_.add (inputsClone); + } + else + batch_.add(null); + } + } + + // Batch requires that input types are exact, we perform no input cross conversion for Batch. + // If so, this is an external semantic, and should go into the release notes + public int[] executeBatch() throws SqlException, BatchUpdateException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "executeBatch"); + int[] updateCounts = null; + updateCounts = executeBatchX (false); + + if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "executeBatch", updateCounts); + return updateCounts; + } + } + + public java.sql.ResultSetMetaData getMetaData () throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "getMetaData"); + ColumnMetaData resultSetMetaData = getMetaDataX(); + if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "getMetaData", resultSetMetaData); + return resultSetMetaData; + } + } + + private ColumnMetaData getMetaDataX () throws SqlException + { + super.checkForClosedStatement(); + return resultSetMetaData_; + } + + //------------------------- JDBC 3.0 ----------------------------------- + + public boolean execute (String sql, int autoGeneratedKeys) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "execute", sql, autoGeneratedKeys); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.execute (String sql, int autoGeneratedKeys) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.execute () with no arguments."); + } + + public boolean execute (String sql, String[] columnNames) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "execute", sql, columnNames); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.execute (String sql, String[] columnNames) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.execute () with no arguments."); + } + + public boolean execute (String sql, int[] columnIndexes) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "execute", sql, columnIndexes); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.execute (String sql, int[] columnIndexes) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.execute () with no arguments."); + } + + public int executeUpdate (String sql, int autoGeneratedKeys) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "executeUpdate", autoGeneratedKeys); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.executeUpdate (String sql, int autoGeneratedKeys) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.executeUpdate () with no arguments."); + } + + public int executeUpdate (String sql, String[] columnNames) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "executeUpdate", columnNames); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.executeUpdate (String sql, String[] columnNames) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.executeUpdate () with no arguments."); + } + + public int executeUpdate (String sql, int[] columnIndexes) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "executeUpdate", columnIndexes); + throw new SqlException (agent_.logWriter_, + "The method java.sql.Statement.executeUpdate (String sql, int[] columnIndexes) cannot be called on a " + + " prepared statement instance." + + " Use java.sql.PreparedStatement.executeUpdate () with no arguments."); + } + + public void setURL (int parameterIndex, java.net.URL x) throws SqlException + { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setURL", parameterIndex, x); + throw new SqlException (agent_.logWriter_, "JDBC 3 method called - not yet supported"); + } + + public java.sql.ParameterMetaData getParameterMetaData() throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "getParameterMetaData"); + Object parameterMetaData = getParameterMetaDataX(); + if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "getParameterMetaData", parameterMetaData); + return (java.sql.ParameterMetaData) parameterMetaData; + } + } + + private ParameterMetaData getParameterMetaDataX() throws SqlException + { + super.checkForClosedStatement(); + ParameterMetaData pm = new ParameterMetaData (parameterMetaData_ != null + ? parameterMetaData_ + : new ColumnMetaData(agent_.logWriter_, 0)); + if (escapedProcedureCallWithResult_) + pm.escapedProcedureCallWithResult_ = true; + return pm; + } + + // ------------------------ box car and callback methods -------------------------------- + + public void writeExecute (Section section, + ColumnMetaData parameterMetaData, + Object[] inputs, + int numInputColumns, + boolean outputExpected, + // This is a hint to the material layer that more write commands will follow. + // It is ignored by the driver in all cases except when blob data is written, + // in which case this boolean is used to optimize the implementation. + // Otherwise we wouldn't be able to chain after blob data is sent. + // Current servers have a restriction that blobs can only be chained with blobs + boolean chainedWritesFollowingSetLob + ) throws SqlException + { materialPreparedStatement_.writeExecute_ (section, + parameterMetaData, + inputs, + numInputColumns, + outputExpected, + chainedWritesFollowingSetLob); + } + + + public void readExecute () throws SqlException + { materialPreparedStatement_.readExecute_(); } + + public void writeOpenQuery (Section section, + int fetchSize, + int resultSetType, + int numInputColumns, + ColumnMetaData parameterMetaData, + Object[] inputs + ) throws SqlException + { materialPreparedStatement_.writeOpenQuery_ (section, + fetchSize, + resultSetType, + numInputColumns, + parameterMetaData, + inputs);} + public void writeDescribeInput (Section section) throws SqlException + { materialPreparedStatement_.writeDescribeInput_ (section); } + public void readDescribeInput () throws SqlException + { materialPreparedStatement_.readDescribeInput_(); } + + public void completeDescribeInput (ColumnMetaData parameterMetaData, Sqlca sqlca) + { + int sqlcode = super.completeSqlca (sqlca); + if (sqlcode < 0) return; + + + parameterMetaData_ = parameterMetaData; + + // The following code handles the case when + // sqlxParmmode is not supported, in which case server will return 0 (unknown), and + // this could clobber our guessed value for sqlxParmmode. This is a problem. + // We can solve this problem for Non-CALL statements, since the parmmode is always IN (1). + // But what about CALL statements. If CALLs are describable, then we have no + // problem, we assume server won't return unknown. + // If CALLs are not describable then nothing gets clobbered because we won't + // parse out extended describe, so again no problem. + if (sqlMode_ != isCall__ && parameterMetaData_ != null) + for (int i = 0; i < parameterMetaData_.columns_; i++) + parameterMetaData_.sqlxParmmode_[i] = 1; // 1 means IN parameter + + if (agent_.loggingEnabled()) agent_.logWriter_.traceParameterMetaData (this, parameterMetaData_); + } + + public void writeDescribeOutput (Section section) throws SqlException + { materialPreparedStatement_.writeDescribeOutput_ (section); } + public void readDescribeOutput () throws SqlException + { materialPreparedStatement_.readDescribeOutput_(); } + public void completeDescribeOutput (ColumnMetaData resultSetMetaData, Sqlca sqlca) + { + int sqlcode = super.completeSqlca (sqlca); + if (sqlcode < 0) return; + resultSetMetaData_ = resultSetMetaData; + if (agent_.loggingEnabled()) agent_.logWriter_.traceResultSetMetaData (this, resultSetMetaData); + } + + void writePrepareDescribeInputOutput () throws SqlException + { + // Notice that sql_ is passed in since in general ad hoc sql must be passed in for unprepared statements + writePrepareDescribeOutput (sql_, section_); + writeDescribeInput (section_); + } + + void readPrepareDescribeInputOutput () throws SqlException + { + readPrepareDescribeOutput (); + readDescribeInput (); + completePrepareDescribe(); + } + + void writePrepareDescribeInput () throws SqlException + { + // performance will be better if we flow prepare with output enable vs. prepare then describe input for callable + // Notice that sql_ is passed in since in general ad hoc sql must be passed in for unprepared statements + writePrepare (sql_, section_); + writeDescribeInput (section_); + } + + void readPrepareDescribeInput () throws SqlException + { + readPrepare(); + readDescribeInput (); + completePrepareDescribe(); + } + + void completePrepareDescribe () + { + if (parameterMetaData_ == null) return; + parameters_ = expandObjectArray (parameters_, parameterMetaData_.columns_); + parameterSet_ = expandBooleanArray (parameterSet_, parameterMetaData_.columns_); + parameterRegistered_ = expandBooleanArray (parameterRegistered_, parameterMetaData_.columns_); + } + + private Object[] expandObjectArray (Object[] array, int newLength) + { + if (array == null) { + Object[] newArray = new Object[newLength]; + return newArray; + } + if (array.length < newLength) { + Object[] newArray = new Object[newLength]; + System.arraycopy (array, 0, newArray, 0, array.length); + return newArray; + } + return array; + } + + private boolean[] expandBooleanArray (boolean[] array, int newLength) + { + if (array == null) { + boolean[] newArray = new boolean[newLength]; + return newArray; + } + if (array.length < newLength) { + boolean[] newArray = new boolean[newLength]; + System.arraycopy (array, 0, newArray, 0, array.length); + return newArray; + } + return array; + } + + void flowPrepareForSelectFromInsert () throws SqlException + { + agent_.beginWriteChain (this); + writePrepareDescribeInputOutput (constructSelectFromInsertSQL(sql_), section_); + agent_.flow (this); + readPrepareDescribeInputOutput(); + agent_.endReadChain(); + } + + void writePrepareDescribeInputOutput (String sql, + Section section) throws SqlException + { + // Notice that sql_ is passed in since in general ad hoc sql must be passed in for unprepared statements + writePrepareDescribeOutput (sql, section); + writeDescribeInput (section); + } + + void flowPrepareDescribeInputOutput () throws SqlException + { + agent_.beginWriteChain (this); + if (sqlMode_ == isCall__) { + writePrepareDescribeInput(); + agent_.flow (this); + readPrepareDescribeInput(); + agent_.endReadChain(); + } + else { + writePrepareDescribeInputOutput(); + agent_.flow (this); + readPrepareDescribeInputOutput(); + agent_.endReadChain(); + } + } + + void flowExecute (int executeType) throws SqlException + { + super.checkForClosedStatement(); + super.clearWarningsX(); + super.checkForAppropriateSqlMode (executeType, sqlMode_); + checkThatAllParametersAreSet(); + + if (sqlMode_ == isUpdate__) updateCount_ = 0; + else updateCount_ = -1; + + java.util.Timer queryTimer = null; + QueryTimerTask queryTimerTask = null; + if (timeout_ != 0) { + queryTimer = new java.util.Timer (); // A thread that ticks the seconds + queryTimerTask = new QueryTimerTask (this, queryTimer); + queryTimer.schedule (queryTimerTask, 1000*timeout_); + } + + try { + agent_.beginWriteChain (this); + + boolean piggybackedAutocommit = super.writeCloseResultSets (true); // true means permit auto-commits + + + int numInputColumns = (parameterMetaData_ != null) ? parameterMetaData_.getColumnCount() : 0; + boolean outputExpected = (resultSetMetaData_ != null && resultSetMetaData_.getColumnCount() > 0); + boolean chainAutoCommit = false; + boolean commitSubstituted = false; + boolean repositionedCursor = false; + ResultSet scrollableRS = null; + + switch (sqlMode_) { + case isUpdate__: + if (positionedUpdateCursorName_ != null) + scrollableRS = agent_.sectionManager_.getPositionedUpdateResultSet (positionedUpdateCursorName_); + if (scrollableRS != null && !scrollableRS.isRowsetCursor_) { + repositionedCursor = + scrollableRS.repositionScrollableResultSetBeforeJDBC1PositionedUpdateDelete(); + if (!repositionedCursor) scrollableRS = null; + } + + chainAutoCommit = connection_.willAutoCommitGenerateFlow() && isAutoCommittableStatement_; + + if (sqlUpdateMode_ == isInsertSql__ && generatedKeysColumnNames_ != null) { + writeOpenQuery (section_, + fetchSize_, + resultSetType_, + numInputColumns, + parameterMetaData_, + parameters_); + } + else { + boolean chainOpenQueryForAutoGeneratedKeys = (sqlUpdateMode_ == isInsertSql__ && autoGeneratedKeys_ == RETURN_GENERATED_KEYS); + writeExecute (section_, + parameterMetaData_, + parameters_, + numInputColumns, + outputExpected, + (chainAutoCommit || chainOpenQueryForAutoGeneratedKeys)// chain flag + ); // chain flag + + if (chainOpenQueryForAutoGeneratedKeys) { + prepareAutoGeneratedKeysStatement (); + writeOpenQuery (preparedStatementForAutoGeneratedKeys_.section_, + preparedStatementForAutoGeneratedKeys_.fetchSize_, + preparedStatementForAutoGeneratedKeys_.resultSetType_); + } + } + + if (chainAutoCommit) { + // we have encountered an error in writing the execute, so do not + // flow an autocommit + if (agent_.accumulatedReadExceptions_ != null) { + // currently, the only write exception we encounter is for + // data truncation: SQLSTATE 01004, so we don't bother checking for this + connection_.writeCommitSubstitute_ (); + commitSubstituted = true; + } + else { + // there is no write error, so flow the commit + connection_.writeCommit (); + } + } + break; + + case isQuery__: + writeOpenQuery (section_, + fetchSize_, + resultSetType_, + numInputColumns, + parameterMetaData_, + parameters_); + break; + + case isCall__: + writeExecuteCall (outputRegistered_, // if no out/inout parameter, outputExpected = false + null, + section_, + fetchSize_, + false, // do not suppress ResultSets for regular CALLs + resultSetType_, + parameterMetaData_, + parameters_); // cross conversion + break; + } + + agent_.flow (this); + + super.readCloseResultSets (true); // true means permit auto-commits + + // turn inUnitOfWork_ flag back on and add statement + // back on commitListeners_ list if they were off + // by an autocommit chained to a close cursor. + if (piggybackedAutocommit) { + connection_.completeTransactionStart(); + } + + super.markResultSetsClosed(); + + switch (sqlMode_) { + case isUpdate__: + // do not need to reposition for a rowset cursor + if (scrollableRS != null && !scrollableRS.isRowsetCursor_) + scrollableRS.readPositioningFetch_(); + + if (sqlUpdateMode_ == isInsertSql__ && generatedKeysColumnNames_ != null) { + readOpenQuery (); + if (resultSet_ != null) { + generatedKeysResultSet_ = resultSet_; + resultSet_ = null; + updateCount_ = 1; + } + } + else { + readExecute (); + + if (sqlUpdateMode_ == isInsertSql__ && autoGeneratedKeys_ == RETURN_GENERATED_KEYS) { + readPrepareAutoGeneratedKeysStatement (); + preparedStatementForAutoGeneratedKeys_.readOpenQuery (); + generatedKeysResultSet_ = preparedStatementForAutoGeneratedKeys_.resultSet_; + preparedStatementForAutoGeneratedKeys_.resultSet_ = null; + } + } + + if (chainAutoCommit) { + if (commitSubstituted) + connection_.readCommitSubstitute_ (); + else + connection_.readCommit (); + } + break; + + case isQuery__: + try { + readOpenQuery (); + } + catch (DisconnectException dise ) { + throw dise; + } + catch (SqlException e) { + throw e; + } + // resultSet_ is null if open query failed. + // check for null resultSet_ before using it. + if (resultSet_ != null) { + resultSet_.parseScrollableRowset (); + //if (resultSet_.scrollable_) resultSet_.getRowCount(); + // If client's cursor name is set, map the client's cursor name to the ResultSet + // Else map the server's cursor name to the ResultSet + mapCursorNameToResultSet (); + } + break; + + case isCall__: + readExecuteCall(); + break; + + } + + + try { + agent_.endReadChain(); + } + catch (SqlException e) { + throw e; + + } + + if (sqlMode_ == isCall__) { + parseStorProcReturnedScrollableRowset (); + // When there are no result sets back, we will commit immediately when autocommit is true. + // make sure a commit is not performed when making the call to the sqlca message procedure + if (connection_.autoCommit_ && resultSet_ == null && resultSetList_ == null && isAutoCommittableStatement_) { + connection_.flowAutoCommit(); + } + } + + // Throw an exception if holdability returned by the server is different from requested. + if (resultSet_ != null && resultSet_.resultSetHoldability_ != resultSetHoldability_ && sqlMode_ != isCall__) + throw new SqlException (agent_.logWriter_, "Unable to open resultSet with requested " + + "holdability " + resultSetHoldability_ + "."); + + } + finally { + if (timeout_ != 0) { // query timers need to be cancelled. + queryTimer.cancel(); + queryTimerTask.cancel(); + } + } + + } + + public int[] executeBatchX (boolean supportsQueryBatchRequest) throws SqlException, BatchUpdateException + { + synchronized (connection_) { + checkForClosedStatement (); // Per jdbc spec (see Statement.close() javadoc) + clearWarningsX (); // Per jdbc spec 0.7, also see getWarnings() javadoc + return executeBatchRequestX (supportsQueryBatchRequest); + } + } + + + private int[] executeBatchRequestX (boolean supportsQueryBatchRequest) + throws SqlException, BatchUpdateException + { + SqlException chainBreaker = null; + int batchSize = batch_.size(); + int[] updateCounts = new int[batchSize]; + int numInputColumns = parameterMetaData_== null ? 0 : parameterMetaData_.getColumnCount(); + Object[] savedInputs = null; // used to save/restore existing parameters + + if (batchSize == 0) return updateCounts; + + // Initialize all the updateCounts to indicate failure + // This is done to account for "chain-breaking" errors where we cannot + // read any more replies + for (int i = 0; i < batchSize; i++) + updateCounts[i] = -3; + + if (!supportsQueryBatchRequest && sqlMode_ == isQuery__) + throw new BatchUpdateException (agent_.logWriter_, "Batching of queries not allowed by J2EE compliance", updateCounts); + if (supportsQueryBatchRequest && sqlMode_ != isQuery__) + throw new BatchUpdateException (agent_.logWriter_, "Query batch requested on a non-query statement", updateCounts); + + resultSetList_ = null; + + + if (sqlMode_ == isQuery__) { + indexOfCurrentResultSet_ = -1; //reset ResultSetList + resultSetList_ = new ResultSet[batchSize]; + } + + + //save the current input set so it can be restored + savedInputs = parameters_; + + agent_.beginBatchedWriteChain (this); + boolean chainAutoCommit = connection_.willAutoCommitGenerateFlow() && isAutoCommittableStatement_; + + for (int i = 0; i < batchSize; i++) { + parameters_ = (Object[]) batch_.get (i); + + if (sqlMode_ != isCall__) { + boolean outputExpected = (resultSetMetaData_ != null && resultSetMetaData_.getColumnCount() > 0); + + writeExecute (section_, + parameterMetaData_, + parameters_, + numInputColumns, + outputExpected, + chainAutoCommit || (i != batchSize - 1)); // more statements to chain + } + else if (outputRegistered_) // make sure no output parameters are registered + throw new BatchUpdateException (agent_.logWriter_, "No output parameters are allowed in batch updates", updateCounts); + else { + writeExecuteCall (false, // no output expected for batched CALLs + null, // no procedure name supplied for prepared CALLs + section_, + fetchSize_, + true, // suppress ResultSets for batch + resultSetType_, + parameterMetaData_, + parameters_); + } + } + + boolean commitSubstituted = false; + if (chainAutoCommit) { + // we have encountered an error in writing the execute, so do not + // flow an autocommit + if (agent_.accumulatedReadExceptions_ != null) { + // currently, the only write exception we encounter is for + // data truncation: SQLSTATE 01004, so we don't bother checking for this + connection_.writeCommitSubstitute_ (); + commitSubstituted = true; + } + else { + // there is no write error, so flow the commit + connection_.writeCommit (); + } + } + + agent_.flowBatch (this, batchSize); + + try { + for (int i = 0; i < batchSize; i++) { + agent_.setBatchedExceptionLabelIndex (i); + parameters_ = (Object[]) batch_.get (i); + if (sqlMode_ != isCall__) + readExecute(); + else + readExecuteCall(); + updateCounts[i] = updateCount_; + + } + + agent_.disableBatchedExceptionTracking(); // to prvent the following readCommit() from getting a batch label + if (chainAutoCommit) { + if (!commitSubstituted) { + connection_.readCommit (); + } + else { + connection_.readCommitSubstitute_ (); + } + } + } + + // for chain-breaking exception only, all read() methods do their own accumulation + // this catches the entire accumulated chain, we need to be careful not to + // reaccumulate it on the agent since the batch labels will be overwritten if + // batch exception tracking is enabled. + catch (SqlException e) { // for chain-breaking exception only + chainBreaker = e; + chainBreaker.setNextException (new SqlException (agent_.logWriter_, + "Non-recoverable chain-breaking exception occurred during batch processing. " + + "The batch is terminated non-atomically.")); + } + // We need to clear the batch before any exception is thrown from agent_.endBatchedReadChain(). + batch_.clear (); + + // restore the saved input set, setting it to "current" + parameters_ = savedInputs; + + agent_.endBatchedReadChain (updateCounts, chainBreaker); + + return updateCounts; + + } + + + //------------------material layer event callbacks follow----------------------- + + boolean listenToUnitOfWork_ = false; + + public void listenToUnitOfWork() + { + if (!listenToUnitOfWork_) { + listenToUnitOfWork_ = true; + connection_.CommitAndRollbackListeners_.add(this); + } + } + + public void completeLocalCommit (java.util.Iterator listenerIterator) + { + if (section_ != null ) openOnServer_ = false; + listenerIterator.remove(); + listenToUnitOfWork_ = false; + } + + public void completeLocalRollback (java.util.Iterator listenerIterator) + { + if (section_ != null ) openOnServer_ = false; + listenerIterator.remove(); + listenToUnitOfWork_ = false; + } + + //----------------------------internal use only helper methods---------------- + + private int checkSetterPreconditions (int parameterIndex) throws SqlException + { + super.checkForClosedStatement(); + parameterIndex = checkForEscapedCallWithResult (parameterIndex); + checkForValidParameterIndex (parameterIndex); + return parameterIndex; + } + + void checkForValidParameterIndex (int parameterIndex) throws SqlException + { + if (parameterMetaData_ == null || parameterIndex < 1 || parameterIndex > parameterMetaData_.columns_) + throw new SqlException (agent_.logWriter_, "Invalid argument: parameter index " + + parameterIndex + " is out of range."); + } + + private void checkThatAllParametersAreSet () throws SqlException + { + if (parameterMetaData_ != null) { + for (int i = 0; i < parameterMetaData_.columns_; i++) + if (!parameterSet_[i] && !parameterRegistered_[i]) + throw new SqlException (agent_.logWriter_, "At least one parameter to the current statement is uninitialized.", "07000"); + } + } + + + private int checkForEscapedCallWithResult (int parameterIndex) throws SqlException + { + if (escapedProcedureCallWithResult_) { + if (parameterIndex == 1) + throw new SqlException (agent_.logWriter_, + "Invalid attempt to set the return value parameter of a CALL statement." + + "Return value parameter of {?=CALL foo(?,?)} statement is parameter 1."); + else + parameterIndex--; + } + return parameterIndex; + } + + void checkForValidScale (int scale) throws SqlException + { + if (scale < 0 || scale > 31) + throw new SqlException (agent_.logWriter_, "Invalid argument: scale must be greater than or equal to 0 and less than 32."); + } + + void checkScaleForINOUTDecimal (int parameterIndex, int registerOutScale) throws SqlException + { + java.math.BigDecimal decimalInput = (java.math.BigDecimal) parameters_[parameterIndex - 1]; + if (decimalInput == null) return; + // if the register out scale is greater than input scale, input scale is stored in sqlScale_ + if (registerOutScale > parameterMetaData_.sqlScale_[parameterIndex - 1]) { + int inputLength = decimalInput.toString().length(); + int scaleDifference = registerOutScale - decimalInput.scale(); + if (decimalInput.signum() == -1) { + inputLength--; + } + // if the new Decimal (with bigger scale) cannot fit into the DA + if ((32 - scaleDifference) < inputLength) { + throw new SqlException (agent_.logWriter_, "The scale supplied by the registerOutParameter method does " + + "not match with the setter method. Possible loss of precision!"); + } + // if the new Decimal (with bigger scale) can fit + else { + parameters_[parameterIndex - 1] = decimalInput.setScale (registerOutScale); + parameterMetaData_.sqlScale_[parameterIndex - 1] = registerOutScale; + } + } + // if the register out sacle is smaller than input scale + else if (registerOutScale < parameterMetaData_.sqlScale_[parameterIndex - 1]) { + // remove 0's at the end of input + try { + // if the new Decimal (with smaller scale) can fit + parameters_[parameterIndex - 1] = decimalInput.setScale (registerOutScale); + parameterMetaData_.sqlScale_[parameterIndex - 1] = registerOutScale; + } + catch (ArithmeticException e) + { + // if the new Decimal (with smaller scale) cannot fit into the DA + throw new SqlException (agent_.logWriter_, "The scale supplied by the registerOutParameter method does " + + "not match with the setter method. Possible loss of precision!"); + } + } + } + + public void close () throws SqlException + { + synchronized (connection_) { + if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "close"); + closeX(); + } + } + + // An untraced version of close() + public void closeX () throws SqlException + { + if (!openOnClient_) return; + super.closeX(); + if (parameterMetaData_ != null) { + parameterMetaData_.markClosed(); + parameterMetaData_ = null; + } + sql_ = null; + + // Apparently, the JVM is not smart enough to traverse parameters_[] and null + // out its members when the entire array is set to null (parameters_=null;). + if (parameters_ != null) + for (int i = 0; i < parameters_.length; i++) { parameters_[i] = null; } + parameters_ = null; + + connection_.CommitAndRollbackListeners_.remove(this); + } + +} Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatement.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatementCallbackInterface.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatementCallbackInterface.java?rev=165178&view=auto ============================================================================== --- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatementCallbackInterface.java (added) +++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatementCallbackInterface.java Thu Apr 28 12:05:42 2005 @@ -0,0 +1,36 @@ +/* + + Derby - Class org.apache.derby.client.am.PreparedStatementCallbackInterface + + Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +package org.apache.derby.client.am; + +// Methods implemented by the common Prepared Statement class to handle +// certain events that may originate from the material or common layers. +// +// Reply implementations may update prepared statement state via this interface. +// +// The event interfaces are undergoing change, new events will be added soon +// We want coarse grained event methods, rather than fine-grained events +public interface PreparedStatementCallbackInterface extends StatementCallbackInterface +{ + + public void completeDescribeInput (ColumnMetaData parameterMetaData, Sqlca sqlca); + public void completeDescribeOutput (ColumnMetaData resultSetMetaData, Sqlca sqlca); + +} Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/PreparedStatementCallbackInterface.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ProductLevel.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ProductLevel.java?rev=165178&view=auto ============================================================================== --- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ProductLevel.java (added) +++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ProductLevel.java Thu Apr 28 12:05:42 2005 @@ -0,0 +1,95 @@ +/* + + Derby - Class org.apache.derby.client.am.ProductLevel + + Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +package org.apache.derby.client.am; + +public class ProductLevel +{ + public String databaseProductName_; + public int versionLevel_; + public int releaseLevel_; + public int modificationLevel_; + + // The following value is sent in the srvrlslv level + public String databaseProductVersion_; + + // The productID is set by the constructors. + // dabaseProductVersion added by derby to include srvrlslv + public ProductLevel (String productID, String databaseProductName, + String srvrlslv) + { + // this.productID has the following format + // CSS for Derby + // vv = version id + // rr = release id + // m = modification level + versionLevel_ = Integer.parseInt (productID.substring (3, 5)); + releaseLevel_ = Integer.parseInt (productID.substring (5, 7)); + modificationLevel_ = Integer.parseInt (productID.substring (7, 8)); + databaseProductName_ = (databaseProductName == null) ? + "Derby" : databaseProductName; // This is the srvclsnm in PROTOCOL. + + // databaseProductVersion - extracted from the srvrlslv. + // srvrlslv has the format <PRDID>/<ALTERNATE VERSION FORMAT> + // for example Derby has a four part verison number so might send + // CSS10000/10.0.1.1 beta. If the alternate version format is not + // specified, + // databaseProductVersion_ will just be set to the srvrlslvl. + // final fallback will be the product id. + // this is the value returned with the getDatabaseProductVersion() + // metadata call + int dbVersionOffset = 0; + if (srvrlslv != null) + { + dbVersionOffset = srvrlslv.indexOf('/') + 1; + // if there was no '/' dbVersionOffset will just be 0 + databaseProductVersion_ = srvrlslv.substring(dbVersionOffset); + } + if (databaseProductVersion_ == null) + databaseProductVersion_ = productID; + } + + public boolean greaterThanOrEqualTo (int versionLevel, int releaseLevel, int modificationLevel) + { + if (versionLevel_ > versionLevel) + return true; + else if (versionLevel_ == versionLevel) { + if (releaseLevel_ > releaseLevel) + return true; + else if (releaseLevel_ == releaseLevel) + if (modificationLevel_ >= modificationLevel) + return true; + } + return false; + } + + public boolean lessThan (int versionLevel, int releaseLevel, int modificationLevel) + { + if (versionLevel_ < versionLevel) + return true; + else if (versionLevel_ == versionLevel) { + if (releaseLevel_ < releaseLevel) + return true; + else if (releaseLevel_ == releaseLevel) + if (modificationLevel_ < modificationLevel) + return true; + } + return false; + } +} Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ProductLevel.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/QueryTimerTask.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/QueryTimerTask.java?rev=165178&view=auto ============================================================================== --- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/QueryTimerTask.java (added) +++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/QueryTimerTask.java Thu Apr 28 12:05:42 2005 @@ -0,0 +1,55 @@ +/* + + Derby - Class org.apache.derby.client.am.QueryTimerTask + + Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +package org.apache.derby.client.am; + +public class QueryTimerTask extends java.util.TimerTask +{ + private Statement statement_; + private java.util.Timer timer_; + + public QueryTimerTask (Statement statement, java.util.Timer timer) + { + statement_ = statement; + timer_ = timer; + } + + public void run () + { + timer_.cancel(); // method call on java.util.Timer to kill the timer thread that triggered this task thread + try { + statement_.cancel(); // jdbc cancel + } + catch (SqlException e) { + SqlWarning warning = new SqlWarning (statement_.agent_.logWriter_, + "An exception occurred while trying to cancel a statement that has timed out." + + " See chained SQLException."); + warning.setNextException (e); + statement_.accumulateWarning (warning); + } + boolean notYetRun = this.cancel(); // method call on java.util.TimerTask to kill this task thread. + if (notYetRun) { + // The following is most likely just a bugcheck - but we'll see. + // May be able to remove it later. + SqlWarning warning = new SqlWarning (statement_.agent_.logWriter_, + "An unexpected error occurred while trying to cancel a statement that has timed out."); + statement_.accumulateWarning (warning); + } + } +} Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/QueryTimerTask.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ResourceUtilities.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ResourceUtilities.java?rev=165178&view=auto ============================================================================== --- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ResourceUtilities.java (added) +++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ResourceUtilities.java Thu Apr 28 12:05:42 2005 @@ -0,0 +1,63 @@ +/* + + Derby - Class org.apache.derby.client.am.ResourceUtilities + + Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +package org.apache.derby.client.am; + +import org.apache.derby.client.resources.ResourceKeys; + +public final class ResourceUtilities +{ + private final static Object[] emptyArgs__ = new Object[] {}; + + // Get resourced text and substitute arguments into text delimited with {i} + // using Java's builtin message formatter. + static public String getResource (String key, Object[] args) + { + try { + return java.text.MessageFormat.format (Configuration.dncResources__.getString (key), args); + } + catch (java.util.MissingResourceException e) { + try { + return java.text.MessageFormat.format ( + Configuration.dncResources__.getString (ResourceKeys.missingResource__01), + new Object[] {e.getKey(), e.getClassName ()}); + } + catch (java.util.MissingResourceException e2) { + return java.text.MessageFormat.format ( + "No resource for key {0} could be found in resource bundle {1}.", + new Object[] {e.getKey(), e.getClassName ()}); + } + } + } + + static public String getResource (String key) + { + return getResource (key, emptyArgs__); + } + + // This method is necessary for java.text.MessageFormat.format to work + // properly because arguments may not be null. + static String getMessage (java.lang.Exception e) + { + return (e.getMessage() == null) ? "" : e.getMessage(); + } + +} + Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ResourceUtilities.java ------------------------------------------------------------------------------ svn:eol-style = native