0001: /*
0002:
0003: Derby - Class org.apache.derby.client.am.ResultSet
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to You under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derby.client.am;
0023:
0024: import java.io.IOException;
0025: import java.io.InputStream;
0026: import java.io.Reader;
0027: import java.sql.SQLException;
0028: import org.apache.derby.client.am.SQLExceptionFactory;
0029: import org.apache.derby.shared.common.reference.SQLState;
0030: import org.apache.derby.shared.common.i18n.MessageUtil;
0031:
0032: public abstract class ResultSet implements java.sql.ResultSet,
0033: ResultSetCallbackInterface {
0034: //---------------------navigational members-----------------------------------
0035:
0036: public Statement statement_;
0037: public ColumnMetaData resultSetMetaData_; // As obtained from the SQLDA
0038: private SqlWarning warnings_;
0039: public Cursor cursor_;
0040: protected Agent agent_;
0041:
0042: public Section generatedSection_ = null;
0043:
0044: private CloseFilterInputStream is_;
0045:
0046: //---------------------navigational cheat-links-------------------------------
0047: // Cheat-links are for convenience only, and are not part of the conceptual model.
0048: // Warning:
0049: // Cheat-links should only be defined for invariant state data.
0050: // That is, the state data is set by the constructor and never changes.
0051:
0052: // Alias for statement_.connection
0053: public final Connection connection_;
0054:
0055: //----------------------------- constants ------------------------------------
0056:
0057: public final static int scrollOrientation_relative__ = 1;
0058: public final static int scrollOrientation_absolute__ = 2;
0059: public final static int scrollOrientation_after__ = 3;
0060: public final static int scrollOrientation_before__ = 4;
0061: public final static int scrollOrientation_prior__ = 5;
0062: public final static int scrollOrientation_first__ = 6;
0063: public final static int scrollOrientation_last__ = 7;
0064: public final static int scrollOrientation_current__ = 8;
0065: public final static int scrollOrientation_next__ = 0;
0066:
0067: public final static int updatability_unknown__ = 0;
0068: public final static int updatability_readOnly__ = 1;
0069: public final static int updatability_delete__ = 2;
0070: public final static int updatability_update__ = 4;
0071:
0072: public final static int sensitivity_unknown__ = 0;
0073: public final static int sensitivity_insensitive__ = 1;
0074: public final static int sensitivity_sensitive_static__ = 2;
0075: public final static int sensitivity_sensitive_dynamic__ = 3;
0076:
0077: static final private int WAS_NULL = 1;
0078: static final private int WAS_NOT_NULL = 2;
0079: static final private int WAS_NULL_UNSET = 0;
0080:
0081: static final public int NEXT_ROWSET = 1;
0082: static final public int PREVIOUS_ROWSET = 2;
0083: static final public int ABSOLUTE_ROWSET = 3;
0084: static final public int FIRST_ROWSET = 4;
0085: static final public int LAST_ROWSET = 5;
0086: static final public int RELATIVE_ROWSET = 6;
0087: static final public int REFRESH_ROWSET = 7;
0088: // determines if a cursor is a:
0089: // Return to Client - not to be read by the stored procedure only by client
0090: // Return to Caller
0091: public static final byte DDM_RETURN_CALLER = 0x01;
0092: public static final byte DDM_RETURN_CLIENT = 0x02;
0093:
0094: //-----------------------------state------------------------------------------
0095:
0096: // Note:
0097: // Result set meta data as described by the SQLDA is described in ColumnMetaData.
0098:
0099: private int wasNull_ = WAS_NULL_UNSET;
0100:
0101: // ResultSet returnability for Stored Procedure cursors
0102: // determines if a cursor is a:
0103: // Return to Client - not to be read by the stored procedure only by client
0104: // Return to Caller - only calling JSP can read it, not the client
0105: protected byte rsReturnability_ = DDM_RETURN_CLIENT;
0106:
0107: // This means the client-side jdbc result set object is open.
0108: boolean openOnClient_ = true;
0109: // This means a server-side DERBY query section (cursor) for this result set is in the open state.
0110: // A jdbc result set may remain open even after the server has closed its cursor
0111: // (openOnClient=true, openOnServer=false); this is known as the "close-only" state.
0112: public boolean openOnServer_ = true;
0113:
0114: // there is a query terminating sqlca returned from the server when the server closes
0115: // it's cursor and the client moves to the close-only state.
0116: public Sqlca queryTerminatingSqlca_;
0117:
0118: // Only true for forward cursors after next() returns false (+100).
0119: // Used to prevent multiple commits for subsequent next() calls.
0120: boolean autoCommitted_ = false;
0121:
0122: // Before the first call to next() or any cursor positioning method, the cursor position is invalid
0123: // and getter methods cannot be called.
0124: // Also, if a cursor is exhausted (+100), the cursor position is invalid.
0125: public boolean isValidCursorPosition_ = false;
0126:
0127: public boolean cursorHold_;
0128:
0129: // query instance identifier returned on open by uplevel servers.
0130: // this value plus the package information uniquely identifies a query.
0131: // it is 64 bits long and it's value is unarchitected.
0132: public long queryInstanceIdentifier_ = 0;
0133:
0134: public int resultSetType_;
0135: public int resultSetConcurrency_;
0136: public int resultSetHoldability_;
0137: public boolean scrollable_ = false;
0138: public int sensitivity_;
0139: public boolean isRowsetCursor_ = false;
0140: public boolean isBeforeFirst_ = true;
0141: public boolean isAfterLast_ = false;
0142: public boolean isFirst_ = false;
0143: public boolean isLast_ = false;
0144: public boolean rowsetContainsLastRow_ = false;
0145: public Sqlca[] rowsetSqlca_;
0146:
0147: // Gets its initial value from the statement when the result set is created.
0148: // It can be modified by setFetchSize and retrieved via getFetchSize.
0149: protected int suggestedFetchSize_;
0150:
0151: // Set by the net layer based on suggestedFetchSize_, protocol
0152: // type, scrollability and presence of lobs.
0153: public int fetchSize_;
0154:
0155: public int fetchDirection_;
0156:
0157: public long rowCount_ = -1;
0158:
0159: protected long absolutePosition_ = 0; // absolute position of the current row
0160: protected long firstRowInRowset_ = 0; // absolute position of the first row in the current rowset
0161: protected long lastRowInRowset_ = 0; // absolute position of the last row in the current rowset
0162: protected long currentRowInRowset_ = -1; // relative position to the first row in the current rowsetwel
0163:
0164: protected long absoluteRowNumberForTheIntendedRow_;
0165:
0166: private boolean isOnInsertRow_ = false; // reserved for later
0167: protected boolean isOnCurrentRow_ = true;
0168: public int rowsReceivedInCurrentRowset_ = 0; // keep track of the number of rows received in the
0169: // current rowset so far
0170:
0171: // maybe be able to consolidate with rowsReceivedInCurrentRowset_
0172: // Could use the rowsReceivedInCurrentRowset_ flag. But since we are going to set it to the
0173: // fetchSize and decrement it each time we successfully receiveds a row, the name will be confusing.
0174: // Fetch size can be changed in the middle of a rowset, and since we don't pre-parse all the rows \
0175: // for forward-only cursors like we do for scrollable cursors, we will lose the original fetchSize
0176: // when it's reset. By decrementing rowsYetToBeReceivedInRowset_, when we come across a fetch
0177: // request, if rowsYetToBeReceivedInRowset_ is 0, then we can fetch using the "new" fetchSize,
0178: // otherwise, we will use rowsYetToBeReceivedInRowset_ to complete the rowset.
0179: public int rowsYetToBeReceivedForRowset_ = 0; // keep track of the number of rows still need to
0180: // be received to complete the rowset
0181:
0182: private Object updatedColumns_[];
0183:
0184: // Keeps track of whether a column has been updated. If a column is updated to null,
0185: // the object array updatedColumns_ entry is null, and we will use this array to distinguish
0186: // between column not updated and column updated to null.
0187: private boolean columnUpdated_[];
0188:
0189: public PreparedStatement preparedStatementForUpdate_;
0190: public PreparedStatement preparedStatementForDelete_;
0191: public PreparedStatement preparedStatementForInsert_;
0192:
0193: // Nesting level of the result set in a stored procedure
0194: public int nestingLevel_ = -1;
0195:
0196: // Whenever a commit occurs, it unpositions the cursor on the server. We need to
0197: // reposition the cursor before updating/deleting again. This flag will be set to true
0198: // whenever a commit happens, and reset to false again after we repositoin the cursor.
0199: public boolean cursorUnpositionedOnServer_ = false;
0200:
0201: // Keep maxRows in the ResultSet, so that changes to maxRow in the statement
0202: // do not affect the resultSet after it has been created
0203: private int maxRows_;
0204:
0205: private boolean[] streamUsedFlags_;
0206:
0207: //---------------------constructors/finalizer---------------------------------
0208:
0209: protected ResultSet(Agent agent, Statement statement,
0210: Cursor cursor, int resultSetType, int resultSetConcurrency,
0211: int resultSetHoldability) {
0212: agent_ = agent;
0213: statement_ = statement;
0214: connection_ = statement_.connection_;
0215: cursor_ = cursor;
0216: if (cursor_ != null) {
0217: cursor_.maxFieldSize_ = statement_.maxFieldSize_;
0218: }
0219: resultSetType_ = resultSetType;
0220: resultSetConcurrency_ = resultSetConcurrency;
0221: resultSetHoldability_ = resultSetHoldability;
0222: fetchDirection_ = statement_.fetchDirection_;
0223: suggestedFetchSize_ = statement_.fetchSize_;
0224:
0225: maxRows_ = statement_.maxRows_;
0226:
0227: // Only set the warning if actual resultSetType returned by the server is less
0228: // than the application requested resultSetType.
0229: // TYPE_FORWARD_ONLY = 1003
0230: // TYPE_SCROLL_INSENSITIVE = 1004
0231: // TYPE_SCROLL_SENSITIVE = 1005
0232: if (resultSetType_ < statement_.resultSetType_) {
0233: statement_.accumulateWarning(new SqlWarning(
0234: agent_.logWriter_, new ClientMessageId(
0235: SQLState.INVALID_RESULTSET_TYPE),
0236: new Integer(statement_.resultSetType_),
0237: new Integer(resultSetType_)));
0238: }
0239:
0240: // Only set the warning if actual resultSetConcurrency returned by the server is
0241: // less than the application requested resultSetConcurrency.
0242: // CONCUR_READ_ONLY = 1007
0243: // CONCUR_UPDATABLE = 1008
0244: if (resultSetConcurrency_ < statement_.resultSetConcurrency_) {
0245: accumulateWarning(new SqlWarning(
0246: agent_.logWriter_,
0247: new ClientMessageId(
0248: SQLState.QUERY_NOT_QUALIFIED_FOR_UPDATABLE_RESULTSET)));
0249:
0250: }
0251:
0252: listenToUnitOfWork();
0253: }
0254:
0255: // ---------------------------jdbc 1------------------------------------------
0256:
0257: public final boolean next() throws SQLException {
0258: try {
0259: synchronized (connection_) {
0260: if (agent_.loggingEnabled()) {
0261: agent_.logWriter_.traceEntry(this , "next");
0262: }
0263: boolean isValidCursorPosition = nextX();
0264: if (agent_.loggingEnabled()) {
0265: agent_.logWriter_.traceExit(this , "next",
0266: isValidCursorPosition);
0267: }
0268: return isValidCursorPosition;
0269: }
0270: } catch (SqlException se) {
0271: throw se.getSQLException();
0272: }
0273: }
0274:
0275: // used by DBMD
0276: boolean nextX() throws SqlException {
0277: checkForClosedResultSet();
0278: clearWarningsX();
0279:
0280: moveToCurrentRowX();
0281:
0282: wasNull_ = ResultSet.WAS_NULL_UNSET;
0283:
0284: // discard all previous updates when moving the cursor
0285: resetUpdatedColumns();
0286:
0287: unuseStreams();
0288:
0289: // for TYPE_FORWARD_ONLY ResultSet, just call cursor.next()
0290: if (resultSetType_ == java.sql.ResultSet.TYPE_FORWARD_ONLY) {
0291: // cursor is null for singleton selects that do not return data.
0292: isValidCursorPosition_ = (cursor_ == null) ? false
0293: : cursor_.next();
0294:
0295: // for forward-only cursors, if qryrowset was specificed on OPNQRY or EXCSQLSTT,
0296: // then we must count the rows returned in the rowset to make sure we received a
0297: // complete rowset. if not, we need to complete the rowset on the next fetch.
0298: if (fetchSize_ != 0) {
0299: if (rowsYetToBeReceivedForRowset_ == 0) {
0300: rowsYetToBeReceivedForRowset_ = fetchSize_;
0301: }
0302: if (isValidCursorPosition_) {
0303: rowsYetToBeReceivedForRowset_--;
0304: }
0305: }
0306:
0307: // Auto-commit semantics for exhausted cursors follows.
0308: // From Connection.setAutoCommit() javadoc:
0309: // The commit occurs when the statement completes or the next execute occurs, whichever comes first.
0310: // In the case of statements returning a ResultSet object, the statement completes when the
0311: // last row of the ResultSet object has been retrieved or the ResultSet object has been closed.
0312: // In advanced cases, a single statement may return multiple results as well as output parameter values.
0313: // In these cases, the commit occurs when all results and output parameter values have been retrieved.
0314: // we will check to see if the forward only result set has gone past the end,
0315: // we will close the result set, the autocommit logic is in the closeX() method
0316: //
0317: //Aug 24, 2005: Auto-commit logic is no longer in the closeX() method. Insted it has been
0318: //moved to Statement and is handled in a manner similar to the embedded driver.
0319: // if (!isValidCursorPosition_ && // We've gone past the end (+100)
0320: // cursor_ != null) {
0321: if ((!isValidCursorPosition_ && cursor_ != null)
0322: || (maxRows_ > 0 && cursor_.rowsRead_ > maxRows_)) {
0323: isValidCursorPosition_ = false;
0324:
0325: // if not on a valid row and the query is closed at the server.
0326: // check for an error which may have caused the cursor to terminate.
0327: // if there were no more rows because of an error, then this method
0328: // should throw an SqlException rather than just returning false.
0329: // depending on how this works with scrollable cursors, there may be
0330: // a better way/more common place for this logic.
0331: SqlException sqlException = null;
0332: if (!openOnServer_) {
0333: int sqlcode = Utils
0334: .getSqlcodeFromSqlca(queryTerminatingSqlca_);
0335: if (sqlcode > 0 && sqlcode != 100) {
0336: accumulateWarning(new SqlWarning(
0337: agent_.logWriter_,
0338: queryTerminatingSqlca_));
0339: } else if (sqlcode < 0) {
0340: sqlException = new SqlException(
0341: agent_.logWriter_,
0342: queryTerminatingSqlca_);
0343: }
0344: }
0345:
0346: try {
0347: statement_.resultSetCommitting(this );
0348: } catch (SqlException sqle) {
0349: sqlException = Utils.accumulateSQLException(sqle,
0350: sqlException);
0351: }
0352:
0353: if (sqlException != null)
0354: throw sqlException;
0355: }
0356: }
0357:
0358: // for scrollable ResultSet's,
0359: // if the "next" request is still fetching within the current rowset,
0360: // update column info from cache and increment the current row index
0361: // else
0362: // fetch the next rowset from the server
0363: else {
0364:
0365: // These flags will only be used for dynamic cursors where we don't know the row count
0366: // and can't keep track of the absolute position of the cursor.
0367: isAfterLast_ = false;
0368: isLast_ = false;
0369:
0370: // if the next row is still within the current rowset
0371: if (rowIsInCurrentRowset(firstRowInRowset_
0372: + currentRowInRowset_ + 1, scrollOrientation_next__)) {
0373: isValidCursorPosition_ = true;
0374: currentRowInRowset_++;
0375: } else {
0376: checkAndThrowReceivedQueryTerminatingException();
0377: isValidCursorPosition_ = getNextRowset();
0378: }
0379:
0380: if (isValidCursorPosition_) {
0381: updateColumnInfoFromCache();
0382: // check if there is a non-null SQLCA for the current row for rowset cursors
0383: checkRowsetSqlca();
0384: if (isBeforeFirst_) {
0385: isFirst_ = true;
0386: }
0387: isBeforeFirst_ = false;
0388: } else {
0389: isFirst_ = false;
0390: return isValidCursorPosition_;
0391: }
0392: }
0393:
0394: // for forward-only cursors, check if rowsRead_ > maxRows_.
0395: // for scrollable cursors, check if absolute row number > maxRows_.
0396: // maxRows_ will be ignored by sensitive dynamic cursors since we don't know the rowCount
0397: if (!openOnClient_) {
0398: isValidCursorPosition_ = false;
0399: } else if (sensitivity_ != sensitivity_sensitive_dynamic__
0400: && maxRows_ > 0
0401: && (firstRowInRowset_ + currentRowInRowset_ > maxRows_)) {
0402: isValidCursorPosition_ = false;
0403: }
0404: return isValidCursorPosition_;
0405: }
0406:
0407: public void close() throws SQLException {
0408: try {
0409: synchronized (connection_) {
0410: if (agent_.loggingEnabled()) {
0411: agent_.logWriter_.traceEntry(this , "close");
0412: }
0413: closeX();
0414: }
0415: } catch (SqlException se) {
0416: throw se.getSQLException();
0417: }
0418: }
0419:
0420: // TO DO: when parseEndqryrm() notifies common w/ endQueryCloseOnlyEvent() we need to mark something
0421: // that we later check to drive a commit.
0422: // An untraced version of close()
0423: public final void closeX() throws SqlException {
0424: if (!openOnClient_) {
0425: return;
0426: }
0427: preClose_();
0428: try {
0429: if (openOnServer_) {
0430: flowCloseAndAutoCommitIfNotAutoCommitted();
0431: } else {
0432: statement_.resultSetCommitting(this );
0433: }
0434: } finally {
0435: markClosed(true);
0436: }
0437:
0438: if (statement_.openOnClient_ && statement_.isCatalogQuery_) {
0439: statement_.closeX();
0440: }
0441:
0442: nullDataForGC();
0443: }
0444:
0445: public void nullDataForGC() {
0446: // This method is called by closeX(). We cannot call this if cursor is cached,
0447: // otherwise it will cause NullPointerException's when cursor is reused.
0448: // Cursor is only cached for PreparedStatement's.
0449: if (cursor_ != null && !statement_.isPreparedStatement_) {
0450: cursor_.nullDataForGC();
0451: }
0452: cursor_ = null;
0453: resultSetMetaData_ = null;
0454: }
0455:
0456: void flowCloseAndAutoCommitIfNotAutoCommitted() throws SqlException {
0457: agent_.beginWriteChain(statement_);
0458: boolean performedAutoCommit = writeCloseAndAutoCommit();
0459: agent_.flow(statement_);
0460: readCloseAndAutoCommit(performedAutoCommit);
0461: agent_.endReadChain();
0462: }
0463:
0464: private boolean writeCloseAndAutoCommit() throws SqlException {
0465: // set autoCommitted_ to false so commit will flow following
0466: // close cursor if autoCommit is true.
0467: autoCommitted_ = false;
0468: if (generatedSection_ == null) { // none call statement result set case
0469: writeCursorClose_(statement_.section_);
0470: } else { // call statement result set(s) case
0471: writeCursorClose_(generatedSection_);
0472: }
0473: return statement_.resultSetCommitting(this , true);
0474: }
0475:
0476: private void readCloseAndAutoCommit(boolean readAutoCommit)
0477: throws SqlException {
0478: readCursorClose_();
0479: if (readAutoCommit)
0480: readAutoCommitIfNotAutoCommitted();
0481: }
0482:
0483: void writeClose() throws SqlException {
0484: // set autoCommitted_ to false so commit will flow following
0485: // close cursor if autoCommit is true.
0486: autoCommitted_ = false;
0487: if (generatedSection_ == null) { // none call statement result set case
0488: writeCursorClose_(statement_.section_);
0489: } else { // call statement result set(s) case
0490: writeCursorClose_(generatedSection_);
0491: }
0492: }
0493:
0494: void readClose() throws SqlException {
0495: try {
0496: if (generatedSection_ == null) { // none call statement result set case
0497: readCursorClose_();
0498: } else { // call statement result set(s) case
0499: readCursorClose_();
0500: }
0501: } finally {
0502: markClosed();
0503: }
0504: }
0505:
0506: // precondition: transaction state allows for auto commit to generate flow
0507: private void writeAutoCommitIfNotAutoCommitted()
0508: throws SqlException {
0509: if (connection_.autoCommit_ && !autoCommitted_) {
0510: connection_.writeAutoCommit();
0511: }
0512: }
0513:
0514: private void readAutoCommitIfNotAutoCommitted() throws SqlException {
0515: if (connection_.autoCommit_ && !autoCommitted_) {
0516: connection_.readAutoCommit();
0517: markAutoCommitted();
0518: }
0519: }
0520:
0521: public boolean wasNull() throws SQLException {
0522: try {
0523: if (agent_.loggingEnabled()) {
0524: agent_.logWriter_.traceEntry(this , "wasNull");
0525: }
0526: checkForClosedResultSet();
0527:
0528: if (wasNull_ == ResultSet.WAS_NULL_UNSET) {
0529: throw new SqlException(agent_.logWriter_,
0530: new ClientMessageId(SQLState.WASNULL_INVALID));
0531: }
0532:
0533: if (agent_.loggingEnabled()) {
0534: agent_.logWriter_.traceExit(this , "wasNull",
0535: wasNull_ == ResultSet.WAS_NULL);
0536: }
0537: return wasNull_ == ResultSet.WAS_NULL;
0538: } catch (SqlException se) {
0539: throw se.getSQLException();
0540: }
0541: }
0542:
0543: //------------------- getters on column index --------------------------------
0544:
0545: // Live life on the edge and run unsynchronized
0546: public boolean getBoolean(int column) throws SQLException {
0547: try {
0548: closeCloseFilterInputStream();
0549:
0550: if (agent_.loggingEnabled()) {
0551: agent_.logWriter_
0552: .traceEntry(this , "getBoolean", column);
0553: }
0554: checkGetterPreconditions(column);
0555: boolean result = false;
0556: if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
0557: if (isOnInsertRow_
0558: && updatedColumns_[column - 1] == null) {
0559: result = false;
0560: } else {
0561: result = agent_.crossConverters_
0562: .setBooleanFromObject(
0563: updatedColumns_[column - 1],
0564: resultSetMetaData_.types_[column - 1]);
0565: }
0566: } else {
0567: result = isNull(column) ? false : cursor_
0568: .getBoolean(column);
0569: }
0570: if (agent_.loggingEnabled()) {
0571: agent_.logWriter_.traceExit(this , "getBoolean", result);
0572: }
0573: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0574: return result;
0575: } catch (SqlException se) {
0576: throw se.getSQLException();
0577: }
0578: }
0579:
0580: // Live life on the edge and run unsynchronized
0581: public byte getByte(int column) throws SQLException {
0582: try {
0583: closeCloseFilterInputStream();
0584:
0585: if (agent_.loggingEnabled()) {
0586: agent_.logWriter_.traceEntry(this , "getByte", column);
0587: }
0588: checkGetterPreconditions(column);
0589: byte result = 0;
0590: if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
0591: if ((isOnInsertRow_)
0592: && (updatedColumns_[column - 1] == null)) {
0593: result = 0;
0594: } else {
0595: result = agent_.crossConverters_.setByteFromObject(
0596: updatedColumns_[column - 1],
0597: resultSetMetaData_.types_[column - 1]);
0598: }
0599: } else {
0600: result = isNull(column) ? 0 : cursor_.getByte(column);
0601: }
0602: if (agent_.loggingEnabled()) {
0603: agent_.logWriter_.traceExit(this , "getByte", result);
0604: }
0605: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0606: return result;
0607: } catch (SqlException se) {
0608: throw se.getSQLException();
0609: }
0610: }
0611:
0612: // Live life on the edge and run unsynchronized
0613: public short getShort(int column) throws SQLException {
0614: try {
0615: closeCloseFilterInputStream();
0616:
0617: if (agent_.loggingEnabled()) {
0618: agent_.logWriter_.traceEntry(this , "getShort", column);
0619: }
0620: checkGetterPreconditions(column);
0621: short result = 0;
0622: if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
0623: if (isOnInsertRow_
0624: && updatedColumns_[column - 1] == null) {
0625: result = 0;
0626: } else {
0627: result = ((Short) agent_.crossConverters_
0628: .setObject(java.sql.Types.SMALLINT,
0629: updatedColumns_[column - 1]))
0630: .shortValue();
0631: }
0632: } else {
0633: result = isNull(column) ? 0 : cursor_.getShort(column);
0634: }
0635: if (agent_.loggingEnabled()) {
0636: agent_.logWriter_.traceExit(this , "getShort", result);
0637: }
0638: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0639: return result;
0640: } catch (SqlException se) {
0641: throw se.getSQLException();
0642: }
0643: }
0644:
0645: // Live life on the edge and run unsynchronized
0646: public int getInt(int column) throws SQLException {
0647: try {
0648: closeCloseFilterInputStream();
0649:
0650: if (agent_.loggingEnabled()) {
0651: agent_.logWriter_.traceEntry(this , "getInt", column);
0652: }
0653: checkGetterPreconditions(column);
0654: int result = 0;
0655: if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
0656: if (isOnInsertRow_
0657: && updatedColumns_[column - 1] == null) {
0658: result = 0;
0659: } else {
0660: result = ((Integer) agent_.crossConverters_
0661: .setObject(java.sql.Types.INTEGER,
0662: updatedColumns_[column - 1]))
0663: .intValue();
0664: }
0665: } else {
0666: result = isNull(column) ? 0 : cursor_.getInt(column);
0667: }
0668: if (agent_.loggingEnabled()) {
0669: agent_.logWriter_.traceExit(this , "getInt", result);
0670: }
0671: setWasNull(column); // this is placed here close to the return to minimize risk of race condition.
0672: return result;
0673: } catch (SqlException se) {
0674: throw se.getSQLException();
0675: }
0676: }
0677:
0678: // Live life on the edge and run unsynchronized
0679: public long getLong(int column) throws SQLException {
0680: try {
0681: closeCloseFilterInputStream();
0682:
0683: if (agent_.loggingEnabled()) {
0684: agent_.logWriter_.traceEntry(this , "getLong", column);
0685: }
0686: checkGetterPreconditions(column);
0687: long result = 0;
0688: if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
0689: if (isOnInsertRow_
0690: && updatedColumns_[column - 1] == null) {
0691: result = 0;
0692: } else {
0693: result = ((Long) agent_.crossConverters_.setObject(
0694: java.sql.Types.BIGINT,
0695: updatedColumns_[column - 1])).longValue();
0696: }
0697: } else {
0698: result = isNull(column) ? 0 : cursor_.getLong(column);
0699: }
0700: if (agent_.loggingEnabled()) {
0701: agent_.logWriter_.traceExit(this , "getLong", result);
0702: }
0703: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0704: return result;
0705: } catch (SqlException se) {
0706: throw se.getSQLException();
0707: }
0708: }
0709:
0710: // Live life on the edge and run unsynchronized
0711: public float getFloat(int column) throws SQLException {
0712: try {
0713: closeCloseFilterInputStream();
0714:
0715: if (agent_.loggingEnabled()) {
0716: agent_.logWriter_.traceEntry(this , "getFloat", column);
0717: }
0718: checkGetterPreconditions(column);
0719: float result = 0;
0720: if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
0721: if ((isOnInsertRow_ && updatedColumns_[column - 1] == null)) {
0722: result = 0;
0723: } else {
0724: result = ((Float) agent_.crossConverters_
0725: .setObject(java.sql.Types.REAL,
0726: updatedColumns_[column - 1]))
0727: .floatValue();
0728: }
0729: } else {
0730: result = isNull(column) ? 0 : cursor_.getFloat(column);
0731: }
0732: if (agent_.loggingEnabled()) {
0733: agent_.logWriter_.traceExit(this , "getFloat", result);
0734: }
0735: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0736: return result;
0737: } catch (SqlException se) {
0738: throw se.getSQLException();
0739: }
0740: }
0741:
0742: // Live life on the edge and run unsynchronized
0743: public double getDouble(int column) throws SQLException {
0744: try {
0745: closeCloseFilterInputStream();
0746:
0747: if (agent_.loggingEnabled()) {
0748: agent_.logWriter_.traceEntry(this , "getDouble", column);
0749: }
0750: checkGetterPreconditions(column);
0751: double result = 0;
0752: if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
0753: if (isOnInsertRow_
0754: && updatedColumns_[column - 1] == null) {
0755: result = 0;
0756: } else {
0757: result = ((Double) agent_.crossConverters_
0758: .setObject(java.sql.Types.DOUBLE,
0759: updatedColumns_[column - 1]))
0760: .doubleValue();
0761: }
0762: } else {
0763: result = isNull(column) ? 0 : cursor_.getDouble(column);
0764: }
0765: if (agent_.loggingEnabled()) {
0766: agent_.logWriter_.traceExit(this , "getDouble", result);
0767: }
0768: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0769: return result;
0770: } catch (SqlException se) {
0771: throw se.getSQLException();
0772: }
0773: }
0774:
0775: // Live life on the edge and run unsynchronized
0776: public java.math.BigDecimal getBigDecimal(int column, int scale)
0777: throws SQLException {
0778: try {
0779: closeCloseFilterInputStream();
0780:
0781: if (agent_.loggingEnabled()) {
0782: agent_.logWriter_.traceDeprecatedEntry(this ,
0783: "getBigDecimal", column, scale);
0784: }
0785: checkGetterPreconditions(column);
0786: java.math.BigDecimal result = null;
0787: if (wasNonNullSensitiveUpdate(column)) {
0788: result = ((java.math.BigDecimal) agent_.crossConverters_
0789: .setObject(java.sql.Types.DECIMAL,
0790: updatedColumns_[column - 1])).setScale(
0791: scale, java.math.BigDecimal.ROUND_DOWN);
0792: } else {
0793: result = isNull(column) ? null : cursor_.getBigDecimal(
0794: column).setScale(scale,
0795: java.math.BigDecimal.ROUND_DOWN);
0796: }
0797: if (agent_.loggingEnabled()) {
0798: agent_.logWriter_.traceDeprecatedExit(this ,
0799: "getBigDecimal", result);
0800: }
0801: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0802: return result;
0803: } catch (SqlException se) {
0804: throw se.getSQLException();
0805: }
0806: }
0807:
0808: // Live life on the edge and run unsynchronized
0809: public java.math.BigDecimal getBigDecimal(int column)
0810: throws SQLException {
0811: try {
0812:
0813: closeCloseFilterInputStream();
0814:
0815: if (agent_.loggingEnabled()) {
0816: agent_.logWriter_.traceEntry(this , "getBigDecimal",
0817: column);
0818: }
0819: checkGetterPreconditions(column);
0820: java.math.BigDecimal result = null;
0821: if (wasNonNullSensitiveUpdate(column)) {
0822: result = (java.math.BigDecimal) agent_.crossConverters_
0823: .setObject(java.sql.Types.DECIMAL,
0824: updatedColumns_[column - 1]);
0825: } else {
0826: result = isNull(column) ? null : cursor_
0827: .getBigDecimal(column);
0828: }
0829: if (agent_.loggingEnabled()) {
0830: agent_.logWriter_.traceExit(this , "getBigDecimal",
0831: result);
0832: }
0833: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0834: return result;
0835: } catch (SqlException se) {
0836: throw se.getSQLException();
0837: }
0838: }
0839:
0840: // Live life on the edge and run unsynchronized
0841: public java.sql.Date getDate(int column) throws SQLException {
0842: try {
0843: closeCloseFilterInputStream();
0844:
0845: if (agent_.loggingEnabled()) {
0846: agent_.logWriter_.traceEntry(this , "getDate", column);
0847: }
0848: checkGetterPreconditions(column);
0849: java.sql.Date result = null;
0850: if (wasNonNullSensitiveUpdate(column)) {
0851: result = (java.sql.Date) agent_.crossConverters_
0852: .setObject(java.sql.Types.DATE,
0853: updatedColumns_[column - 1]);
0854: } else {
0855: result = isNull(column) ? null : cursor_
0856: .getDate(column);
0857: }
0858: if (agent_.loggingEnabled()) {
0859: agent_.logWriter_.traceExit(this , "getDate", result);
0860: }
0861: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0862: return result;
0863: } catch (SqlException se) {
0864: throw se.getSQLException();
0865: }
0866: }
0867:
0868: // Live life on the edge and run unsynchronized
0869: public java.sql.Date getDate(int column, java.util.Calendar calendar)
0870: throws SQLException {
0871: try {
0872: closeCloseFilterInputStream();
0873:
0874: if (agent_.loggingEnabled()) {
0875: agent_.logWriter_.traceEntry(this , "getDate", column,
0876: calendar);
0877: }
0878: java.sql.Date date = getDate(column);
0879: if (calendar == null) {
0880: throw new SqlException(agent_.logWriter_,
0881: new ClientMessageId(SQLState.CALENDAR_IS_NULL));
0882: }
0883: if (date != null) {
0884: java.util.Calendar targetCalendar = java.util.Calendar
0885: .getInstance(calendar.getTimeZone());
0886: targetCalendar.clear();
0887: targetCalendar.setTime(date);
0888: java.util.Calendar defaultCalendar = java.util.Calendar
0889: .getInstance();
0890: defaultCalendar.clear();
0891: defaultCalendar.setTime(date);
0892: long timeZoneOffset = targetCalendar
0893: .get(java.util.Calendar.ZONE_OFFSET)
0894: - defaultCalendar
0895: .get(java.util.Calendar.ZONE_OFFSET)
0896: + targetCalendar
0897: .get(java.util.Calendar.DST_OFFSET)
0898: - defaultCalendar
0899: .get(java.util.Calendar.DST_OFFSET);
0900: date.setTime(date.getTime() - timeZoneOffset);
0901: }
0902: if (agent_.loggingEnabled()) {
0903: agent_.logWriter_.traceExit(this , "getDate", date);
0904: }
0905: return date;
0906: } catch (SqlException se) {
0907: throw se.getSQLException();
0908: }
0909: }
0910:
0911: // Live life on the edge and run unsynchronized
0912: public java.sql.Time getTime(int column) throws SQLException {
0913: try {
0914: closeCloseFilterInputStream();
0915:
0916: if (agent_.loggingEnabled()) {
0917: agent_.logWriter_.traceEntry(this , "getTime", column);
0918: }
0919: checkGetterPreconditions(column);
0920: java.sql.Time result = null;
0921: if (wasNonNullSensitiveUpdate(column)) {
0922: result = (java.sql.Time) agent_.crossConverters_
0923: .setObject(java.sql.Types.TIME,
0924: updatedColumns_[column - 1]);
0925: } else {
0926: result = isNull(column) ? null : cursor_
0927: .getTime(column);
0928: }
0929: if (agent_.loggingEnabled()) {
0930: agent_.logWriter_.traceExit(this , "getTime", result);
0931: }
0932: setWasNull(column); // Placed close to the return to minimize risk of thread interference
0933: return result;
0934: } catch (SqlException se) {
0935: throw se.getSQLException();
0936: }
0937: }
0938:
0939: // Live life on the edge and run unsynchronized
0940: public java.sql.Time getTime(int column, java.util.Calendar calendar)
0941: throws SQLException {
0942: try {
0943: closeCloseFilterInputStream();
0944:
0945: if (agent_.loggingEnabled()) {
0946: agent_.logWriter_.traceEntry(this , "getTime", column,
0947: calendar);
0948: }
0949: java.sql.Time time = getTime(column);
0950: if (calendar == null) {
0951: throw new SqlException(agent_.logWriter_,
0952: new ClientMessageId(SQLState.CALENDAR_IS_NULL));
0953: }
0954: if (time != null) {
0955: java.util.Calendar targetCalendar = java.util.Calendar
0956: .getInstance(calendar.getTimeZone());
0957: targetCalendar.clear();
0958: targetCalendar.setTime(time);
0959: java.util.Calendar defaultCalendar = java.util.Calendar
0960: .getInstance();
0961: defaultCalendar.clear();
0962: defaultCalendar.setTime(time);
0963: long timeZoneOffset = targetCalendar
0964: .get(java.util.Calendar.ZONE_OFFSET)
0965: - defaultCalendar
0966: .get(java.util.Calendar.ZONE_OFFSET)
0967: + targetCalendar
0968: .get(java.util.Calendar.DST_OFFSET)
0969: - defaultCalendar
0970: .get(java.util.Calendar.DST_OFFSET);
0971: time.setTime(time.getTime() - timeZoneOffset);
0972: }
0973: if (agent_.loggingEnabled()) {
0974: agent_.logWriter_.traceExit(this , "getTime", time);
0975: }
0976: return time;
0977: } catch (SqlException se) {
0978: throw se.getSQLException();
0979: }
0980: }
0981:
0982: // Live life on the edge and run unsynchronized
0983: public java.sql.Timestamp getTimestamp(int column)
0984: throws SQLException {
0985: try {
0986: closeCloseFilterInputStream();
0987:
0988: if (agent_.loggingEnabled()) {
0989: agent_.logWriter_.traceEntry(this , "getTimestamp",
0990: column);
0991: }
0992: checkGetterPreconditions(column);
0993: java.sql.Timestamp result = null;
0994: if (wasNonNullSensitiveUpdate(column)) {
0995: result = (java.sql.Timestamp) agent_.crossConverters_
0996: .setObject(java.sql.Types.TIMESTAMP,
0997: updatedColumns_[column - 1]);
0998: } else {
0999: result = isNull(column) ? null : cursor_
1000: .getTimestamp(column);
1001: }
1002: if (agent_.loggingEnabled()) {
1003: agent_.logWriter_.traceExit(this , "getTimestamp",
1004: result);
1005: }
1006: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1007: return result;
1008: } catch (SqlException se) {
1009: throw se.getSQLException();
1010: }
1011: }
1012:
1013: // Live life on the edge and run unsynchronized
1014: public java.sql.Timestamp getTimestamp(int column,
1015: java.util.Calendar calendar) throws SQLException {
1016: try {
1017: closeCloseFilterInputStream();
1018:
1019: if (agent_.loggingEnabled()) {
1020: agent_.logWriter_.traceEntry(this , "getTimestamp",
1021: column, calendar);
1022: }
1023: java.sql.Timestamp timestamp = getTimestamp(column);
1024: if (calendar == null) {
1025: throw new SqlException(agent_.logWriter_,
1026: new ClientMessageId(SQLState.CALENDAR_IS_NULL));
1027: }
1028: if (timestamp != null) {
1029: int nano = timestamp.getNanos();
1030: java.util.Calendar targetCalendar = java.util.Calendar
1031: .getInstance(calendar.getTimeZone());
1032: targetCalendar.clear();
1033: targetCalendar.setTime(timestamp);
1034: java.util.Calendar defaultCalendar = java.util.Calendar
1035: .getInstance();
1036: defaultCalendar.clear();
1037: defaultCalendar.setTime(timestamp);
1038: long timeZoneOffset = targetCalendar
1039: .get(java.util.Calendar.ZONE_OFFSET)
1040: - defaultCalendar
1041: .get(java.util.Calendar.ZONE_OFFSET)
1042: + targetCalendar
1043: .get(java.util.Calendar.DST_OFFSET)
1044: - defaultCalendar
1045: .get(java.util.Calendar.DST_OFFSET);
1046: timestamp.setTime(timestamp.getTime() - timeZoneOffset);
1047: timestamp.setNanos(nano);
1048: }
1049: if (agent_.loggingEnabled()) {
1050: agent_.logWriter_.traceExit(this , "getTimestamp",
1051: timestamp);
1052: }
1053: return timestamp;
1054: } catch (SqlException se) {
1055: throw se.getSQLException();
1056: }
1057: }
1058:
1059: // Live life on the edge and run unsynchronized
1060: public String getString(int column) throws SQLException {
1061: try {
1062: closeCloseFilterInputStream();
1063:
1064: if (agent_.loggingEnabled()) {
1065: agent_.logWriter_.traceEntry(this , "getString", column);
1066: }
1067: checkGetterPreconditions(column);
1068: String result = null;
1069: if (wasNonNullSensitiveUpdate(column)) {
1070: result = (String) agent_.crossConverters_.setObject(
1071: java.sql.Types.CHAR,
1072: updatedColumns_[column - 1]);
1073: } else {
1074: result = isNull(column) ? null : cursor_
1075: .getString(column);
1076: }
1077: if (agent_.loggingEnabled()) {
1078: agent_.logWriter_.traceExit(this , "getString", result);
1079: }
1080: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1081: return result;
1082: } catch (SqlException se) {
1083: throw se.getSQLException();
1084: }
1085: }
1086:
1087: // Live life on the edge and run unsynchronized
1088: public byte[] getBytes(int column) throws SQLException {
1089: try {
1090: closeCloseFilterInputStream();
1091:
1092: if (agent_.loggingEnabled()) {
1093: agent_.logWriter_.traceEntry(this , "getBytes", column);
1094: }
1095: checkGetterPreconditions(column);
1096: byte[] result = null;
1097: if (wasNonNullSensitiveUpdate(column)) {
1098: result = (byte[]) agent_.crossConverters_.setObject(
1099: java.sql.Types.BINARY,
1100: updatedColumns_[column - 1]);
1101: } else {
1102: result = isNull(column) ? null : cursor_
1103: .getBytes(column);
1104: }
1105: if (agent_.loggingEnabled()) {
1106: agent_.logWriter_.traceExit(this , "getBytes", result);
1107: }
1108: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1109: return result;
1110: } catch (SqlException se) {
1111: throw se.getSQLException();
1112: }
1113: }
1114:
1115: // Live life on the edge and run unsynchronized
1116: public java.io.InputStream getBinaryStream(int column)
1117: throws SQLException {
1118: try {
1119: closeCloseFilterInputStream();
1120:
1121: if (agent_.loggingEnabled()) {
1122: agent_.logWriter_.traceEntry(this , "getBinaryStream",
1123: column);
1124: }
1125:
1126: checkGetterPreconditions(column);
1127: useStream(column);
1128:
1129: java.io.InputStream result = null;
1130: if (wasNonNullSensitiveUpdate(column)) {
1131: result = new java.io.ByteArrayInputStream(
1132: (byte[]) agent_.crossConverters_.setObject(
1133: java.sql.Types.BINARY,
1134: updatedColumns_[column - 1]));
1135: } else {
1136: result = isNull(column) ? null : cursor_
1137: .getBinaryStream(column);
1138: }
1139: if (agent_.loggingEnabled()) {
1140: agent_.logWriter_.traceExit(this , "getBinaryStream",
1141: result);
1142: }
1143: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1144: return createCloseFilterInputStream(result);
1145: } catch (SqlException se) {
1146: throw se.getSQLException();
1147: }
1148: }
1149:
1150: // Live life on the edge and run unsynchronized
1151: public java.io.InputStream getAsciiStream(int column)
1152: throws SQLException {
1153: try {
1154: closeCloseFilterInputStream();
1155:
1156: if (agent_.loggingEnabled()) {
1157: agent_.logWriter_.traceEntry(this , "getAsciiStream",
1158: column);
1159: }
1160:
1161: checkGetterPreconditions(column);
1162: useStream(column);
1163:
1164: java.io.InputStream result = null;
1165: if (wasNonNullSensitiveUpdate(column)) {
1166:
1167: result = new AsciiStream(
1168: (String) agent_.crossConverters_.setObject(
1169: java.sql.Types.CHAR,
1170: updatedColumns_[column - 1]));
1171: } else {
1172: result = isNull(column) ? null : cursor_
1173: .getAsciiStream(column);
1174: }
1175: if (agent_.loggingEnabled()) {
1176: agent_.logWriter_.traceExit(this , "getAsciiStream",
1177: result);
1178: }
1179: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1180: return createCloseFilterInputStream(result);
1181: } catch (SqlException se) {
1182: throw se.getSQLException();
1183: }
1184: }
1185:
1186: /**
1187: * Retrieve the value of the specified column as a stream of two-byte
1188: * Unicode characters. Deprecated in JDBC 2.0 and this method will just
1189: * throw a feature not implemented exception.
1190: *
1191: * @param column the column to retrieve as a Unicode stream
1192: * @exception SQLException throws feature not implemented
1193: */
1194: public java.io.InputStream getUnicodeStream(int column)
1195: throws SQLException {
1196: if (agent_.loggingEnabled()) {
1197: agent_.logWriter_.traceDeprecatedEntry(this ,
1198: "getUnicodeStream", column);
1199: }
1200:
1201: throw SQLExceptionFactory.notImplemented("getUnicodeStream");
1202: }
1203:
1204: // Live life on the edge and run unsynchronized
1205: public java.io.Reader getCharacterStream(int column)
1206: throws SQLException {
1207: try {
1208: closeCloseFilterInputStream();
1209:
1210: if (agent_.loggingEnabled()) {
1211: agent_.logWriter_.traceEntry(this ,
1212: "getCharacterStream", column);
1213: }
1214:
1215: checkGetterPreconditions(column);
1216: useStream(column);
1217:
1218: java.io.Reader result = null;
1219: if (wasNonNullSensitiveUpdate(column)) {
1220: result = new java.io.StringReader(
1221: (String) agent_.crossConverters_.setObject(
1222: java.sql.Types.CHAR,
1223: updatedColumns_[column - 1]));
1224: } else {
1225: result = isNull(column) ? null : cursor_
1226: .getCharacterStream(column);
1227: }
1228: if (agent_.loggingEnabled()) {
1229: agent_.logWriter_.traceExit(this , "getCharacterStream",
1230: result);
1231: }
1232: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1233: return result;
1234: } catch (SqlException se) {
1235: throw se.getSQLException();
1236: }
1237: }
1238:
1239: // Live life on the edge and run unsynchronized
1240: public java.sql.Blob getBlob(int column) throws SQLException {
1241: try {
1242: closeCloseFilterInputStream();
1243:
1244: if (agent_.loggingEnabled()) {
1245: agent_.logWriter_.traceEntry(this , "getBlob", column);
1246: }
1247: checkGetterPreconditions(column);
1248: java.sql.Blob result = null;
1249: if (wasNonNullSensitiveUpdate(column)) {
1250: result = (java.sql.Blob) agent_.crossConverters_
1251: .setObject(java.sql.Types.BLOB,
1252: updatedColumns_[column - 1]);
1253: } else {
1254: result = isNull(column) ? null : cursor_
1255: .getBlob(column);
1256: }
1257: if (agent_.loggingEnabled()) {
1258: agent_.logWriter_.traceExit(this , "getBlob", result);
1259: }
1260: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1261: return result;
1262: } catch (SqlException se) {
1263: throw se.getSQLException();
1264: }
1265: }
1266:
1267: // Live life on the edge and run unsynchronized
1268: public java.sql.Clob getClob(int column) throws SQLException {
1269: try {
1270: closeCloseFilterInputStream();
1271:
1272: if (agent_.loggingEnabled()) {
1273: agent_.logWriter_.traceEntry(this , "getClob", column);
1274: }
1275: checkGetterPreconditions(column);
1276: java.sql.Clob result = null;
1277: if (wasNonNullSensitiveUpdate(column)) {
1278: result = (java.sql.Clob) agent_.crossConverters_
1279: .setObject(java.sql.Types.CLOB,
1280: updatedColumns_[column - 1]);
1281: } else {
1282: result = isNull(column) ? null : cursor_
1283: .getClob(column);
1284: }
1285: if (agent_.loggingEnabled()) {
1286: agent_.logWriter_.traceExit(this , "getClob", result);
1287: }
1288: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1289: return result;
1290: } catch (SqlException se) {
1291: throw se.getSQLException();
1292: }
1293: }
1294:
1295: // Live life on the edge and run unsynchronized
1296: public java.sql.Ref getRef(int column) throws SQLException {
1297: try {
1298: closeCloseFilterInputStream();
1299:
1300: if (agent_.loggingEnabled()) {
1301: agent_.logWriter_.traceEntry(this , "getRef", column);
1302: }
1303: checkGetterPreconditions(column);
1304: java.sql.Ref result = isNull(column) ? null : cursor_
1305: .getRef(column);
1306: if (true) {
1307: throw new SqlException(agent_.logWriter_,
1308: new ClientMessageId(
1309: SQLState.JDBC_METHOD_NOT_IMPLEMENTED));
1310: }
1311: if (agent_.loggingEnabled()) {
1312: agent_.logWriter_.traceExit(this , "getRef", result);
1313: }
1314: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1315: return result;
1316: } catch (SqlException se) {
1317: throw se.getSQLException();
1318: }
1319: }
1320:
1321: // Live life on the edge and run unsynchronized
1322: public java.sql.Array getArray(int column) throws SQLException {
1323: try {
1324: closeCloseFilterInputStream();
1325:
1326: if (agent_.loggingEnabled()) {
1327: agent_.logWriter_.traceEntry(this , "getArray", column);
1328: }
1329: checkGetterPreconditions(column);
1330: java.sql.Array result = isNull(column) ? null : cursor_
1331: .getArray(column);
1332: if (true) {
1333: throw new SqlException(agent_.logWriter_,
1334: new ClientMessageId(
1335: SQLState.JDBC_METHOD_NOT_IMPLEMENTED));
1336: }
1337: if (agent_.loggingEnabled()) {
1338: agent_.logWriter_.traceExit(this , "getArray", result);
1339: }
1340: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1341: return result;
1342: } catch (SqlException se) {
1343: throw se.getSQLException();
1344: }
1345: }
1346:
1347: // Live life on the edge and run unsynchronized
1348: public Object getObject(int column) throws SQLException {
1349: try {
1350: closeCloseFilterInputStream();
1351:
1352: if (agent_.loggingEnabled()) {
1353: agent_.logWriter_.traceEntry(this , "getObject", column);
1354: }
1355: Object result = getObjectX(column);
1356: if (agent_.loggingEnabled()) {
1357: agent_.logWriter_.traceExit(this , "getObject", result);
1358: }
1359: return result;
1360: } catch (SqlException se) {
1361: throw se.getSQLException();
1362: }
1363: }
1364:
1365: // used by DBMD
1366: Object getObjectX(int column) throws SqlException {
1367: checkGetterPreconditions(column);
1368: Object result = null;
1369: if (wasNonNullSensitiveUpdate(column)) {
1370: result = updatedColumns_[column - 1];
1371: } else {
1372: result = isNull(column) ? null : cursor_.getObject(column);
1373: }
1374: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1375: return result;
1376: }
1377:
1378: // Live life on the edge and run unsynchronized
1379: public Object getObject(int column, java.util.Map map)
1380: throws SQLException {
1381: try {
1382: closeCloseFilterInputStream();
1383:
1384: if (agent_.loggingEnabled()) {
1385: agent_.logWriter_.traceEntry(this , "getObject", column,
1386: map);
1387: }
1388: checkGetterPreconditions(column);
1389: Object result = null;
1390: if (wasNonNullSensitiveUpdate(column)) {
1391: result = updatedColumns_[column - 1];
1392: } else {
1393: result = isNull(column) ? null : cursor_
1394: .getObject(column);
1395: }
1396: if (true) {
1397: throw new SqlException(agent_.logWriter_,
1398: new ClientMessageId(
1399: SQLState.JDBC_METHOD_NOT_IMPLEMENTED));
1400: }
1401: if (agent_.loggingEnabled()) {
1402: agent_.logWriter_.traceExit(this , "getObject", result);
1403: }
1404: setWasNull(column); // Placed close to the return to minimize risk of thread interference
1405: return result;
1406: } catch (SqlException se) {
1407: throw se.getSQLException();
1408: }
1409: }
1410:
1411: //----------------------------------------------------------------------------
1412:
1413: // This method only returns true if there is a new non-null updated value.
1414: // If the resultset is updatable, sensitive, and updated, return the new non-null updated value.
1415: // Otherwise this method will return false.
1416: // If the column is updated to null, or if the column has not been update but is null,
1417: // a null will be returned by isNull(), which first calls wasNullSensitiveUpdate() to check for a column
1418: // that is updated to null, and columnUpdated_ is checked there.
1419: private boolean wasNonNullSensitiveUpdate(int column) {
1420: return updatedColumns_ != null
1421: && updatedColumns_[column - 1] != null;
1422: }
1423:
1424: // if updatedColumns_ entry is null, but columnUpdated_ entry
1425: // indicates column has been updated, then column is updated to null.
1426: private boolean wasNullSensitiveUpdate(int column) {
1427: return updatedColumns_ != null
1428: && updatedColumns_[column - 1] == null
1429: && columnUpdated_[column - 1];
1430: }
1431:
1432: private void setWasNull(int column) {
1433: if (wasNullSensitiveUpdate(column)
1434: || (isOnInsertRow_ && updatedColumns_[column - 1] == null)) {
1435: wasNull_ = WAS_NULL;
1436: } else {
1437: wasNull_ = (cursor_.isNull_ == null || cursor_.isNull_[column - 1]) ? WAS_NULL
1438: : WAS_NOT_NULL;
1439: }
1440: }
1441:
1442: private boolean isNull(int column) {
1443: if (wasNullSensitiveUpdate(column)) {
1444: return true;
1445: } else {
1446: return (cursor_.isUpdateDeleteHole_ == true || cursor_.isNull_[column - 1]);
1447: }
1448: }
1449:
1450: // ------------- Methods for accessing results by column name ----------------
1451:
1452: public final boolean getBoolean(String columnName)
1453: throws SQLException {
1454: try {
1455: if (agent_.loggingEnabled()) {
1456: agent_.logWriter_.traceEntry(this , "getBoolean",
1457: columnName);
1458: }
1459: return getBoolean(findColumnX(columnName));
1460: } catch (SqlException se) {
1461: throw se.getSQLException();
1462: }
1463: }
1464:
1465: public final byte getByte(String columnName) throws SQLException {
1466: try {
1467: if (agent_.loggingEnabled()) {
1468: agent_.logWriter_.traceEntry(this , "getByte",
1469: columnName);
1470: }
1471: return getByte(findColumnX(columnName));
1472: } catch (SqlException se) {
1473: throw se.getSQLException();
1474: }
1475: }
1476:
1477: public final short getShort(String columnName) throws SQLException {
1478: try {
1479: if (agent_.loggingEnabled()) {
1480: agent_.logWriter_.traceEntry(this , "getShort",
1481: columnName);
1482: }
1483: return getShort(findColumnX(columnName));
1484: } catch (SqlException se) {
1485: throw se.getSQLException();
1486: }
1487: }
1488:
1489: public final int getInt(String columnName) throws SQLException {
1490: try {
1491: if (agent_.loggingEnabled()) {
1492: agent_.logWriter_
1493: .traceEntry(this , "getInt", columnName);
1494: }
1495: return getInt(findColumnX(columnName));
1496: } catch (SqlException se) {
1497: throw se.getSQLException();
1498: }
1499: }
1500:
1501: public final long getLong(String columnName) throws SQLException {
1502: try {
1503: if (agent_.loggingEnabled()) {
1504: agent_.logWriter_.traceEntry(this , "getLong",
1505: columnName);
1506: }
1507: return getLong(findColumnX(columnName));
1508: } catch (SqlException se) {
1509: throw se.getSQLException();
1510: }
1511: }
1512:
1513: public final float getFloat(String columnName) throws SQLException {
1514: try {
1515: if (agent_.loggingEnabled()) {
1516: agent_.logWriter_.traceEntry(this , "getFloat",
1517: columnName);
1518: }
1519: return getFloat(findColumnX(columnName));
1520: } catch (SqlException se) {
1521: throw se.getSQLException();
1522: }
1523: }
1524:
1525: public final double getDouble(String columnName)
1526: throws SQLException {
1527: try {
1528: if (agent_.loggingEnabled()) {
1529: agent_.logWriter_.traceEntry(this , "getDouble",
1530: columnName);
1531: }
1532: return getDouble(findColumnX(columnName));
1533: } catch (SqlException se) {
1534: throw se.getSQLException();
1535: }
1536: }
1537:
1538: public final java.math.BigDecimal getBigDecimal(String columnName,
1539: int scale) throws SQLException {
1540: try {
1541: if (agent_.loggingEnabled()) {
1542: agent_.logWriter_.traceDeprecatedEntry(this ,
1543: "getBigDecimal", columnName, scale);
1544: }
1545: return getBigDecimal(findColumnX(columnName), scale);
1546: } catch (SqlException se) {
1547: throw se.getSQLException();
1548: }
1549: }
1550:
1551: public final java.math.BigDecimal getBigDecimal(String columnName)
1552: throws SQLException {
1553: try {
1554: if (agent_.loggingEnabled()) {
1555: agent_.logWriter_.traceEntry(this , "getBigDecimal",
1556: columnName);
1557: }
1558: return getBigDecimal(findColumnX(columnName));
1559: } catch (SqlException se) {
1560: throw se.getSQLException();
1561: }
1562: }
1563:
1564: public final java.sql.Date getDate(String columnName)
1565: throws SQLException {
1566: try {
1567: if (agent_.loggingEnabled()) {
1568: agent_.logWriter_.traceEntry(this , "getDate",
1569: columnName);
1570: }
1571: return getDate(findColumnX(columnName));
1572: } catch (SqlException se) {
1573: throw se.getSQLException();
1574: }
1575: }
1576:
1577: public final java.sql.Date getDate(String columnName,
1578: java.util.Calendar cal) throws SQLException {
1579: try {
1580: if (agent_.loggingEnabled()) {
1581: agent_.logWriter_.traceEntry(this , "getDate",
1582: columnName, cal);
1583: }
1584: return getDate(findColumnX(columnName), cal);
1585: } catch (SqlException se) {
1586: throw se.getSQLException();
1587: }
1588: }
1589:
1590: public final java.sql.Time getTime(String columnName)
1591: throws SQLException {
1592: try {
1593: if (agent_.loggingEnabled()) {
1594: agent_.logWriter_.traceEntry(this , "getTime",
1595: columnName);
1596: }
1597: return getTime(findColumnX(columnName));
1598: } catch (SqlException se) {
1599: throw se.getSQLException();
1600: }
1601: }
1602:
1603: public final java.sql.Time getTime(String columnName,
1604: java.util.Calendar cal) throws SQLException {
1605: try {
1606: if (agent_.loggingEnabled()) {
1607: agent_.logWriter_.traceEntry(this , "getTime",
1608: columnName, cal);
1609: }
1610: return getTime(findColumnX(columnName), cal);
1611: } catch (SqlException se) {
1612: throw se.getSQLException();
1613: }
1614: }
1615:
1616: public final java.sql.Timestamp getTimestamp(String columnName)
1617: throws SQLException {
1618: try {
1619: if (agent_.loggingEnabled()) {
1620: agent_.logWriter_.traceEntry(this , "getTimestamp",
1621: columnName);
1622: }
1623: return getTimestamp(findColumnX(columnName));
1624: } catch (SqlException se) {
1625: throw se.getSQLException();
1626: }
1627: }
1628:
1629: public final java.sql.Timestamp getTimestamp(String columnName,
1630: java.util.Calendar cal) throws SQLException {
1631: try {
1632: if (agent_.loggingEnabled()) {
1633: agent_.logWriter_.traceEntry(this , "getTimestamp",
1634: columnName, cal);
1635: }
1636: return getTimestamp(findColumnX(columnName), cal);
1637: } catch (SqlException se) {
1638: throw se.getSQLException();
1639: }
1640: }
1641:
1642: public final String getString(String columnName)
1643: throws SQLException {
1644: try {
1645: if (agent_.loggingEnabled()) {
1646: agent_.logWriter_.traceEntry(this , "getString",
1647: columnName);
1648: }
1649: return getString(findColumnX(columnName));
1650: } catch (SqlException se) {
1651: throw se.getSQLException();
1652: }
1653: }
1654:
1655: public final byte[] getBytes(String columnName) throws SQLException {
1656: try {
1657: if (agent_.loggingEnabled()) {
1658: agent_.logWriter_.traceEntry(this , "getBytes",
1659: columnName);
1660: }
1661: return getBytes(findColumnX(columnName));
1662: } catch (SqlException se) {
1663: throw se.getSQLException();
1664: }
1665: }
1666:
1667: public final java.io.InputStream getBinaryStream(String columnName)
1668: throws SQLException {
1669: try {
1670: if (agent_.loggingEnabled()) {
1671: agent_.logWriter_.traceEntry(this , "getBinaryStream",
1672: columnName);
1673: }
1674: return getBinaryStream(findColumnX(columnName));
1675: } catch (SqlException se) {
1676: throw se.getSQLException();
1677: }
1678: }
1679:
1680: public final java.io.InputStream getAsciiStream(String columnName)
1681: throws SQLException {
1682: try {
1683: if (agent_.loggingEnabled()) {
1684: agent_.logWriter_.traceEntry(this , "getAsciiStream",
1685: columnName);
1686: }
1687: return getAsciiStream(findColumnX(columnName));
1688: } catch (SqlException se) {
1689: throw se.getSQLException();
1690: }
1691: }
1692:
1693: public final java.io.InputStream getUnicodeStream(String columnName)
1694: throws SQLException {
1695: try {
1696: if (agent_.loggingEnabled()) {
1697: agent_.logWriter_.traceDeprecatedEntry(this ,
1698: "getUnicodeStream", columnName);
1699: }
1700: return getUnicodeStream(findColumnX(columnName));
1701: } catch (SqlException se) {
1702: throw se.getSQLException();
1703: }
1704: }
1705:
1706: public final java.io.Reader getCharacterStream(String columnName)
1707: throws SQLException {
1708: try {
1709: if (agent_.loggingEnabled()) {
1710: agent_.logWriter_.traceEntry(this ,
1711: "getCharacterStream", columnName);
1712: }
1713: return getCharacterStream(findColumnX(columnName));
1714: } catch (SqlException se) {
1715: throw se.getSQLException();
1716: }
1717: }
1718:
1719: public final java.sql.Blob getBlob(String columnName)
1720: throws SQLException {
1721: try {
1722: if (agent_.loggingEnabled()) {
1723: agent_.logWriter_.traceEntry(this , "getBlob",
1724: columnName);
1725: }
1726: return getBlob(findColumnX(columnName));
1727: } catch (SqlException se) {
1728: throw se.getSQLException();
1729: }
1730: }
1731:
1732: public final java.sql.Clob getClob(String columnName)
1733: throws SQLException {
1734: try {
1735: if (agent_.loggingEnabled()) {
1736: agent_.logWriter_.traceEntry(this , "getClob",
1737: columnName);
1738: }
1739: return getClob(findColumnX(columnName));
1740: } catch (SqlException se) {
1741: throw se.getSQLException();
1742: }
1743: }
1744:
1745: public final java.sql.Array getArray(String columnName)
1746: throws SQLException {
1747: try {
1748: if (agent_.loggingEnabled()) {
1749: agent_.logWriter_.traceEntry(this , "getArray",
1750: columnName);
1751: }
1752: return getArray(findColumnX(columnName));
1753: } catch (SqlException se) {
1754: throw se.getSQLException();
1755: }
1756: }
1757:
1758: public final java.sql.Ref getRef(String columnName)
1759: throws SQLException {
1760: try {
1761: if (agent_.loggingEnabled()) {
1762: agent_.logWriter_
1763: .traceEntry(this , "getRef", columnName);
1764: }
1765: return getRef(findColumnX(columnName));
1766: } catch (SqlException se) {
1767: throw se.getSQLException();
1768: }
1769: }
1770:
1771: public final Object getObject(String columnName)
1772: throws SQLException {
1773: try {
1774: if (agent_.loggingEnabled()) {
1775: agent_.logWriter_.traceEntry(this , "getObject",
1776: columnName);
1777: }
1778: return getObject(findColumnX(columnName));
1779: } catch (SqlException se) {
1780: throw se.getSQLException();
1781: }
1782: }
1783:
1784: public final Object getObject(String columnName, java.util.Map map)
1785: throws SQLException {
1786: try {
1787: if (agent_.loggingEnabled()) {
1788: agent_.logWriter_.traceEntry(this , "getObject",
1789: columnName, map);
1790: }
1791: return getObject(findColumnX(columnName), map);
1792: } catch (SqlException se) {
1793: throw se.getSQLException();
1794: }
1795: }
1796:
1797: // ----------------Advanced features -----------------------------------------
1798:
1799: /**
1800: * Returns the first <code>SQLWarning</code> reported on this
1801: * <code>ResultSet</code> object, or <code>null</code> if there
1802: * are no warnings. Subsequent warnings are chained on the
1803: * returned object.
1804: *
1805: * @return the first <code>SQLWarning</code> in the chain, or
1806: * <code>null</code> if no warnings are reported
1807: * @exception SQLException if a database error occurs or the
1808: * result set is closed
1809: */
1810: public final java.sql.SQLWarning getWarnings() throws SQLException {
1811: try {
1812: checkForClosedResultSet();
1813: } catch (SqlException se) {
1814: throw se.getSQLException();
1815: }
1816: if (agent_.loggingEnabled()) {
1817: agent_.logWriter_.traceExit(this , "getWarnings", warnings_);
1818: }
1819: return warnings_ == null ? null : warnings_.getSQLWarning();
1820: }
1821:
1822: /**
1823: * Clear all warnings on this <code>ResultSet</code> and make
1824: * subsequent calls to <code>getWarnings()</code> return
1825: * <code>null</code> until a new warning is reported.
1826: *
1827: * @exception SQLException if a database error occurs or the
1828: * result set is closed
1829: */
1830: public final void clearWarnings() throws SQLException {
1831: synchronized (connection_) {
1832: if (agent_.loggingEnabled()) {
1833: agent_.logWriter_.traceEntry(this , "clearWarnings");
1834: }
1835: try {
1836: checkForClosedResultSet();
1837: } catch (SqlException se) {
1838: throw se.getSQLException();
1839: }
1840: clearWarningsX();
1841: }
1842: }
1843:
1844: // An untraced version of clearWarnings()
1845: public final void clearWarningsX() {
1846: warnings_ = null;
1847: }
1848:
1849: public String getCursorName() throws SQLException {
1850: try {
1851: synchronized (connection_) {
1852: if (agent_.loggingEnabled()) {
1853: agent_.logWriter_.traceEntry(this , "getCursorName");
1854: }
1855: checkForClosedResultSet();
1856: if (generatedSection_ != null) {
1857: return "stored procedure generated cursor:"
1858: + generatedSection_.getServerCursorName();
1859: }
1860: if (statement_.cursorName_ == null) {// cursor name is not assigned yet
1861: statement_.cursorName_ = statement_.section_
1862: .getServerCursorName();
1863: }
1864: if (agent_.loggingEnabled()) {
1865: agent_.logWriter_.traceExit(this , "getCursorName",
1866: statement_.cursorName_);
1867: }
1868: return statement_.cursorName_;
1869: }
1870: } catch (SqlException se) {
1871: throw se.getSQLException();
1872: }
1873: }
1874:
1875: public java.sql.ResultSetMetaData getMetaData() throws SQLException {
1876: try {
1877: if (agent_.loggingEnabled()) {
1878: agent_.logWriter_.traceEntry(this , "getMetaData");
1879: }
1880: java.sql.ResultSetMetaData resultSetMetaData = getMetaDataX();
1881: if (agent_.loggingEnabled()) {
1882: agent_.logWriter_.traceExit(this , "getMetaData",
1883: resultSetMetaData);
1884: }
1885: return resultSetMetaData;
1886: } catch (SqlException se) {
1887: throw se.getSQLException();
1888: }
1889: }
1890:
1891: // used by DBMD
1892: ColumnMetaData getMetaDataX() throws SqlException {
1893: checkForClosedResultSet();
1894: return resultSetMetaData_;
1895: }
1896:
1897: public final int findColumn(String columnName) throws SQLException {
1898: try {
1899: synchronized (connection_) {
1900: if (agent_.loggingEnabled()) {
1901: agent_.logWriter_.traceEntry(this , "findColumn",
1902: columnName);
1903: }
1904: int column = findColumnX(columnName);
1905: if (agent_.loggingEnabled()) {
1906: agent_.logWriter_.traceExit(this , "findColumn",
1907: column);
1908: }
1909: return column;
1910: }
1911: } catch (SqlException se) {
1912: throw se.getSQLException();
1913: }
1914: }
1915:
1916: // An untraced version of findColumn()
1917: private final int findColumnX(String columnName)
1918: throws SqlException {
1919: checkForClosedResultSet();
1920: return resultSetMetaData_.findColumnX(columnName);
1921: }
1922:
1923: //-------------------------- Traversal/Positioning ---------------------------
1924:
1925: public boolean isBeforeFirst() throws SQLException {
1926: try {
1927: if (agent_.loggingEnabled()) {
1928: agent_.logWriter_.traceEntry(this , "isBeforeFirst");
1929: }
1930: checkForClosedResultSet();
1931: checkThatResultSetTypeIsScrollable();
1932: // Returns false if the ResultSet contains no rows.
1933: boolean isBeforeFirst = isBeforeFirstX();
1934: if (agent_.loggingEnabled()) {
1935: agent_.logWriter_.traceExit(this , "isBeforeFirst",
1936: isBeforeFirst);
1937: }
1938: return isBeforeFirst;
1939: } catch (SqlException se) {
1940: throw se.getSQLException();
1941: }
1942: }
1943:
1944: private boolean isBeforeFirstX() throws SqlException {
1945: if (sensitivity_ == sensitivity_sensitive_dynamic__) {
1946: return isBeforeFirst_;
1947: } else
1948: //return ((resultSetContainsNoRows()) ? false : (currentRowInRowset_ == -1));
1949: {
1950: return ((currentRowInRowset_ == -1) && !resultSetContainsNoRows());
1951: }
1952: }
1953:
1954: public boolean isAfterLast() throws SQLException {
1955: try {
1956: if (agent_.loggingEnabled()) {
1957: agent_.logWriter_.traceEntry(this , "isAfterLast");
1958: }
1959: checkForClosedResultSet();
1960: checkThatResultSetTypeIsScrollable();
1961: // Returns false if the ResultSet contains no rows.
1962: boolean isAfterLast = isAfterLastX();
1963: if (agent_.loggingEnabled()) {
1964: agent_.logWriter_.traceExit(this , "isAfterLast",
1965: isAfterLast);
1966: }
1967: return isAfterLast;
1968: } catch (SqlException se) {
1969: throw se.getSQLException();
1970: }
1971: }
1972:
1973: private boolean isAfterLastX() throws SqlException {
1974: if (sensitivity_ == sensitivity_sensitive_dynamic__) {
1975: return isAfterLast_;
1976: } else {
1977: return (resultSetContainsNoRows() ? false
1978: : (firstRowInRowset_ == currentRowInRowset_
1979: && currentRowInRowset_ == lastRowInRowset_
1980: && lastRowInRowset_ == 0 && absolutePosition_ == (maxRows_ == 0 ? rowCount_ + 1
1981: : maxRows_ + 1)));
1982: }
1983: }
1984:
1985: public boolean isFirst() throws SQLException {
1986: try {
1987: if (agent_.loggingEnabled()) {
1988: agent_.logWriter_.traceEntry(this , "isFirst");
1989: }
1990: checkForClosedResultSet();
1991: checkThatResultSetTypeIsScrollable();
1992: // Not necessary to get the rowCount_ since currentRowInRowset_ is initialized to -1,
1993: // and it will not be changed if there is no rows in the ResultSet.
1994: boolean isFirst = isFirstX();
1995: if (agent_.loggingEnabled()) {
1996: agent_.logWriter_.traceExit(this , "isFirst", isFirst);
1997: }
1998: return isFirst;
1999: } catch (SqlException se) {
2000: throw se.getSQLException();
2001: }
2002: }
2003:
2004: private boolean isFirstX() {
2005: if (sensitivity_ == sensitivity_sensitive_dynamic__) {
2006: return isFirst_;
2007: }
2008: return (firstRowInRowset_ == 1 && currentRowInRowset_ == 0);
2009: }
2010:
2011: public boolean isLast() throws SQLException {
2012: try {
2013: if (agent_.loggingEnabled()) {
2014: agent_.logWriter_.traceEntry(this , "isLast");
2015: }
2016: checkForClosedResultSet();
2017: checkThatResultSetTypeIsScrollable();
2018: // Returns false if the ResultSet contains no rows.
2019: boolean isLast = isLastX();
2020: if (agent_.loggingEnabled()) {
2021: agent_.logWriter_.traceExit(this , "isLast", isLast);
2022: }
2023: return isLast;
2024: } catch (SqlException se) {
2025: throw se.getSQLException();
2026: }
2027: }
2028:
2029: private boolean isLastX() throws SqlException {
2030: if (sensitivity_ == sensitivity_sensitive_dynamic__) {
2031: return isLast_;
2032: } else {
2033: return (resultSetContainsNoRows() ? false
2034: : (firstRowInRowset_ + currentRowInRowset_) == rowCount_);
2035: }
2036: }
2037:
2038: public void beforeFirst() throws SQLException {
2039: try {
2040: synchronized (connection_) {
2041: if (agent_.loggingEnabled()) {
2042: agent_.logWriter_.traceEntry(this , "beforeFirst");
2043: }
2044: checkForClosedResultSet();
2045: checkThatResultSetTypeIsScrollable();
2046: clearWarningsX();
2047: beforeFirstX();
2048: }
2049: } catch (SqlException se) {
2050: throw se.getSQLException();
2051: }
2052: }
2053:
2054: private void beforeFirstX() throws SqlException {
2055:
2056: resetRowsetFlags();
2057: unuseStreams();
2058:
2059: moveToCurrentRowX();
2060:
2061: // this method has no effect if the result set has no rows.
2062: // only send cntqry to position the cursor before first if
2063: // resultset contains rows and it is not already before first, or
2064: // if the cursor is a dynamic cursor.
2065: if (sensitivity_ == sensitivity_sensitive_dynamic__
2066: || (!resultSetContainsNoRows() && !isServersCursorPositionBeforeFirst())) {
2067: moveToBeforeFirst();
2068: }
2069: isBeforeFirst_ = true;
2070: setRowsetBeforeFirstEvent();
2071: cursor_.resetDataBuffer();
2072: resetRowsetSqlca();
2073: isValidCursorPosition_ = false;
2074: }
2075:
2076: public void afterLast() throws SQLException {
2077: try {
2078: synchronized (connection_) {
2079: if (agent_.loggingEnabled()) {
2080: agent_.logWriter_.traceEntry(this , "afterLast");
2081: }
2082: checkForClosedResultSet();
2083: checkThatResultSetTypeIsScrollable();
2084: clearWarningsX();
2085: afterLastX();
2086: }
2087: } catch (SqlException se) {
2088: throw se.getSQLException();
2089: }
2090: }
2091:
2092: private void afterLastX() throws SqlException {
2093: resetRowsetFlags();
2094: unuseStreams();
2095:
2096: moveToCurrentRowX();
2097:
2098: // this method has no effect if the result set has no rows.
2099: // only send cntqry to position the cursor after last if
2100: // resultset contains rows and it is not already after last, or
2101: // if the cursor is a dynamic cursor.
2102: if (sensitivity_ == sensitivity_sensitive_dynamic__
2103: || (!resultSetContainsNoRows() && !isServerCursorPositionAfterLast())) {
2104: moveToAfterLast();
2105: }
2106: isAfterLast_ = true;
2107: setRowsetAfterLastEvent();
2108: cursor_.resetDataBuffer();
2109: resetRowsetSqlca();
2110: isValidCursorPosition_ = false;
2111: }
2112:
2113: public boolean first() throws SQLException {
2114: try {
2115: synchronized (connection_) {
2116: if (agent_.loggingEnabled()) {
2117: agent_.logWriter_.traceEntry(this , "first");
2118: }
2119: boolean isValidCursorPosition = firstX();
2120: if (agent_.loggingEnabled()) {
2121: agent_.logWriter_.traceExit(this , "first",
2122: isValidCursorPosition);
2123: }
2124: return isValidCursorPosition;
2125: }
2126: } catch (SqlException se) {
2127: throw se.getSQLException();
2128: }
2129: }
2130:
2131: private boolean firstX() throws SqlException {
2132: checkForClosedResultSet();
2133: checkThatResultSetTypeIsScrollable();
2134: clearWarningsX();
2135:
2136: moveToCurrentRowX();
2137:
2138: wasNull_ = ResultSet.WAS_NULL_UNSET;
2139:
2140: // discard all previous updates when moving the cursor
2141: resetUpdatedColumns();
2142:
2143: resetRowsetFlags();
2144: unuseStreams();
2145:
2146: // if first row is not in the current rowset, fetch the first rowset from the server.
2147: // rowIsInCurrentRowset with orientation first will always return false for dynamic cursors.
2148: if (rowIsInCurrentRowset(1, scrollOrientation_first__)) {
2149: isValidCursorPosition_ = true;
2150: currentRowInRowset_ = 0;
2151: } else {
2152: checkAndThrowReceivedQueryTerminatingException();
2153: isValidCursorPosition_ = getFirstRowset();
2154: }
2155:
2156: if (isValidCursorPosition_) {
2157: updateColumnInfoFromCache();
2158: isFirst_ = true;
2159: // check if there is a non-null SQLCA for the row for rowset cursors
2160: checkRowsetSqlca();
2161: }
2162:
2163: return isValidCursorPosition_;
2164: }
2165:
2166: public boolean last() throws SQLException {
2167: try {
2168: synchronized (connection_) {
2169: if (agent_.loggingEnabled()) {
2170: agent_.logWriter_.traceEntry(this , "last");
2171: }
2172: boolean isValidCursorPosition = lastX();
2173: if (agent_.loggingEnabled()) {
2174: agent_.logWriter_.traceExit(this , "last",
2175: isValidCursorPosition);
2176: }
2177: return isValidCursorPosition;
2178: }
2179: } catch (SqlException se) {
2180: throw se.getSQLException();
2181: }
2182: }
2183:
2184: private boolean lastX() throws SqlException {
2185: checkForClosedResultSet();
2186: checkThatResultSetTypeIsScrollable();
2187: clearWarningsX();
2188:
2189: moveToCurrentRowX();
2190:
2191: wasNull_ = ResultSet.WAS_NULL_UNSET;
2192:
2193: // discard all previous updates when moving the cursor
2194: resetUpdatedColumns();
2195:
2196: resetRowsetFlags();
2197: unuseStreams();
2198:
2199: // only get the rowCount for static cursors.
2200: if (rowCountIsUnknown()) {
2201: getRowCount();
2202: }
2203: long row = rowCount_;
2204: if (sensitivity_ != sensitivity_sensitive_dynamic__
2205: && maxRows_ > 0) {
2206: if (rowCount_ > maxRows_) {
2207: row = maxRows_;
2208: }
2209: }
2210:
2211: // rowIsInCurrentRowset with orientation last will always return false for dynamic cursors.
2212: if (rowIsInCurrentRowset(row, scrollOrientation_last__)) {
2213: isValidCursorPosition_ = true;
2214: currentRowInRowset_ = row - firstRowInRowset_;
2215: } else {
2216: checkAndThrowReceivedQueryTerminatingException();
2217: isValidCursorPosition_ = getLastRowset(row);
2218: }
2219:
2220: if (isValidCursorPosition_) {
2221: updateColumnInfoFromCache();
2222: isLast_ = true;
2223: // check if there is a non-null SQLCA for the current row for rowset cursors
2224: checkRowsetSqlca();
2225: }
2226:
2227: return isValidCursorPosition_;
2228: }
2229:
2230: public int getRow() throws SQLException {
2231: try {
2232: synchronized (connection_) {
2233: if (agent_.loggingEnabled()) {
2234: agent_.logWriter_.traceEntry(this , "getRow");
2235: }
2236: int row = getRowX();
2237: if (agent_.loggingEnabled()) {
2238: agent_.logWriter_.traceExit(this , "getRow", row);
2239: }
2240: return row;
2241: }
2242: } catch (SqlException se) {
2243: throw se.getSQLException();
2244: }
2245: }
2246:
2247: private int getRowX() throws SqlException {
2248: checkForClosedResultSet();
2249: long row;
2250: checkThatResultSetIsNotDynamic();
2251: if (resultSetType_ == java.sql.ResultSet.TYPE_FORWARD_ONLY)
2252: // for forward-only cursors, getRow() should return 0 if cursor is not on a valid row,
2253: // i.e. afterlast.
2254: {
2255: row = (cursor_.allRowsReceivedFromServer() && cursor_
2256: .currentRowPositionIsEqualToNextRowPosition()) ? 0
2257: : cursor_.rowsRead_;
2258: } else {
2259: if (rowCountIsUnknown()) {
2260: // commented out here because the following method is called the first thing
2261: // inside getRowCount();
2262: //checkAndThrowReceivedQueryTerminatingException();
2263: getRowCount();
2264: }
2265: if (rowCount_ == 0 || currentRowInRowset_ < 0) // || currentRowInRowset_ > rowCount_)
2266: {
2267: row = 0;
2268: } else {
2269: row = firstRowInRowset_ + currentRowInRowset_;
2270: }
2271: }
2272: if (row > Integer.MAX_VALUE) {
2273: this .accumulateWarning(new SqlWarning(agent_.logWriter_,
2274: new ClientMessageId(
2275: SQLState.NUMBER_OF_ROWS_TOO_LARGE_FOR_INT),
2276: new Long(row)));
2277: }
2278: return (int) row;
2279: }
2280:
2281: public boolean absolute(int row) throws SQLException {
2282: try {
2283: synchronized (connection_) {
2284: if (agent_.loggingEnabled()) {
2285: agent_.logWriter_.traceEntry(this , "absolute", row);
2286: }
2287: boolean isValidCursorPosition = absoluteX(row);
2288: if (agent_.loggingEnabled()) {
2289: agent_.logWriter_.traceExit(this , "absolute",
2290: isValidCursorPosition);
2291: }
2292: return isValidCursorPosition;
2293: }
2294: } catch (SqlException se) {
2295: throw se.getSQLException();
2296: }
2297: }
2298:
2299: public boolean absoluteX(int row) throws SqlException {
2300: checkForClosedResultSet();
2301: checkThatResultSetTypeIsScrollable();
2302: clearWarningsX();
2303:
2304: moveToCurrentRowX();
2305:
2306: wasNull_ = ResultSet.WAS_NULL_UNSET;
2307:
2308: // discard all previous updates when moving the cursor.
2309: resetUpdatedColumns();
2310:
2311: resetRowsetFlags();
2312: unuseStreams();
2313:
2314: if (maxRows_ > 0) {
2315: // if "row" is positive and > maxRows, fetch afterLast
2316: // else if "row" is negative, and abs(row) > maxRows, fetch beforeFirst
2317: if (row > 0 && row > maxRows_) {
2318: afterLastX();
2319: isValidCursorPosition_ = false;
2320: return isValidCursorPosition_;
2321: } else if (row <= 0 && java.lang.Math.abs(row) > maxRows_) {
2322: beforeFirstX();
2323: isValidCursorPosition_ = false;
2324: return isValidCursorPosition_;
2325: }
2326: }
2327:
2328: int fetchAbsoluteRow = 0;
2329: if (rowCountIsUnknown()) {
2330: getRowCount();
2331: }
2332: if (sensitivity_ == sensitivity_sensitive_dynamic__) {
2333: fetchAbsoluteRow = row;
2334: } else
2335: // calculate the positive absolute row number based on rowCount for static or insensitive cursors.
2336: {
2337: fetchAbsoluteRow = (row >= 0) ? row : (int) (rowCount_
2338: + row + 1);
2339: }
2340:
2341: // rowIsInCurrentRowset with orientation absolute will always return false for dynamic cursors.
2342: if (rowIsInCurrentRowset(fetchAbsoluteRow,
2343: scrollOrientation_absolute__)) {
2344: isValidCursorPosition_ = true;
2345: currentRowInRowset_ = fetchAbsoluteRow - firstRowInRowset_;
2346: } else {
2347: checkAndThrowReceivedQueryTerminatingException();
2348: isValidCursorPosition_ = getAbsoluteRowset(fetchAbsoluteRow);
2349: }
2350:
2351: if (isValidCursorPosition_) {
2352: updateColumnInfoFromCache();
2353: if (row == 1) {
2354: isFirst_ = true;
2355: }
2356: if (row == -1) {
2357: isLast_ = true;
2358: }
2359: // check if there is a non-null SQLCA for the row for rowset cursors
2360: checkRowsetSqlca();
2361: }
2362:
2363: return isValidCursorPosition_;
2364: }
2365:
2366: public boolean relative(int rows) throws SQLException {
2367: try {
2368: synchronized (connection_) {
2369: if (agent_.loggingEnabled()) {
2370: agent_.logWriter_
2371: .traceEntry(this , "relative", rows);
2372: }
2373: boolean isValidCursorPosition = relativeX(rows);
2374: if (agent_.loggingEnabled()) {
2375: agent_.logWriter_.traceExit(this , "relative",
2376: isValidCursorPosition);
2377: }
2378: return isValidCursorPosition;
2379: }
2380: } catch (SqlException se) {
2381: throw se.getSQLException();
2382: }
2383: }
2384:
2385: private boolean relativeX(int rows) throws SqlException {
2386: checkForClosedResultSet();
2387: checkThatResultSetTypeIsScrollable();
2388: clearWarningsX();
2389:
2390: moveToCurrentRowX();
2391:
2392: wasNull_ = ResultSet.WAS_NULL_UNSET;
2393:
2394: // discard all previous updates when moving the cursor.
2395: resetUpdatedColumns();
2396:
2397: unuseStreams();
2398:
2399: // If the resultset is empty, relative(n) is a null operation
2400: if (resultSetContainsNoRows()) {
2401: isValidCursorPosition_ = false;
2402: return isValidCursorPosition_;
2403: }
2404:
2405: // relative(0) is a null-operation, but the retruned result is
2406: // dependent on wether the cursorposition is on a row or not.
2407: // Scroll insensitive updatable should see own changes, so relative(0)
2408: // has to refetch the row.
2409: if (rows == 0) {
2410: if (resultSetConcurrency_ == ResultSet.CONCUR_UPDATABLE
2411: && resultSetType_ == ResultSet.TYPE_SCROLL_INSENSITIVE) {
2412: // re-fetch currentRow
2413: isValidCursorPosition_ = getAbsoluteRowset(absolutePosition_);
2414: } else {
2415: if (isBeforeFirstX() || isAfterLastX()) {
2416: isValidCursorPosition_ = false;
2417: } else {
2418: isValidCursorPosition_ = true;
2419: }
2420: }
2421: return isValidCursorPosition_;
2422: }
2423:
2424: // Handle special cases when the cursor is before first or
2425: // after last, since the following code assumes we ar on a
2426: // valid cursor
2427: if (isBeforeFirstX()) {
2428: if (rows > 0) {
2429: nextX();
2430: return relativeX(rows - 1);
2431: } else {
2432: isValidCursorPosition_ = false;
2433: return isValidCursorPosition_;
2434: }
2435: }
2436: if (isAfterLastX()) {
2437: if (rows < 0) {
2438: previousX();
2439: return relativeX(rows + 1);
2440: } else {
2441: isValidCursorPosition_ = false;
2442: return isValidCursorPosition_;
2443: }
2444: }
2445: // Ok, now we are on a row and ready to do some real positioning.....
2446:
2447: resetRowsetFlags();
2448:
2449: // currentAbsoluteRowNumber is used for static cursors only.
2450: long currentAbsoluteRowNumber = firstRowInRowset_
2451: + currentRowInRowset_;
2452:
2453: // if "rows" is positive, and currentRow+rows > maxRows, fetch afterLast.
2454: // if "rows" is negative, and if the absolute value of "rows" is greater than
2455: // the currentrow number, will fetch beforeFirst anyways. do not need to check
2456: // for maxRows.
2457: if (sensitivity_ != sensitivity_sensitive_dynamic__
2458: && maxRows_ > 0 && rows > 0
2459: && currentAbsoluteRowNumber + rows > maxRows_) {
2460: afterLastX();
2461: isValidCursorPosition_ = false;
2462: return isValidCursorPosition_;
2463: }
2464:
2465: if (rowIsInCurrentRowset(currentAbsoluteRowNumber + rows,
2466: scrollOrientation_relative__)) {
2467: currentRowInRowset_ += rows;
2468: isValidCursorPosition_ = true;
2469: } else {
2470: checkAndThrowReceivedQueryTerminatingException();
2471: long rowNumber = (sensitivity_ == sensitivity_sensitive_dynamic__) ? currentRowInRowset_
2472: + rows
2473: : currentAbsoluteRowNumber + rows
2474: - absolutePosition_;
2475: if (maxRows_ < Math.abs(rowNumber) && maxRows_ != 0) {
2476: if (rowNumber > 0) {
2477: afterLastX();
2478: } else {
2479: beforeFirstX();
2480: }
2481: isValidCursorPosition_ = false;
2482: return isValidCursorPosition_;
2483: }
2484: isValidCursorPosition_ = getRelativeRowset(rowNumber);
2485: }
2486:
2487: if (isValidCursorPosition_) {
2488: updateColumnInfoFromCache();
2489: // check if there is a non-null SQLCA for the row for rowset cursors
2490: checkRowsetSqlca();
2491: }
2492:
2493: return isValidCursorPosition_;
2494: }
2495:
2496: public boolean previous() throws SQLException {
2497: try {
2498: synchronized (connection_) {
2499: if (agent_.loggingEnabled()) {
2500: agent_.logWriter_.traceEntry(this , "previous");
2501: }
2502: boolean isValidCursorPosition = previousX();
2503: if (agent_.loggingEnabled()) {
2504: agent_.logWriter_.traceExit(this , "previous",
2505: isValidCursorPosition);
2506: }
2507: return isValidCursorPosition;
2508: }
2509: } catch (SqlException se) {
2510: throw se.getSQLException();
2511: }
2512: }
2513:
2514: private boolean previousX() throws SqlException {
2515: checkForClosedResultSet();
2516: checkThatResultSetTypeIsScrollable();
2517: clearWarningsX();
2518:
2519: moveToCurrentRowX();
2520:
2521: wasNull_ = ResultSet.WAS_NULL_UNSET;
2522:
2523: // discard all previous updates when moving the cursor.
2524: resetUpdatedColumns();
2525:
2526: unuseStreams();
2527:
2528: isBeforeFirst_ = false;
2529: isFirst_ = false;
2530:
2531: if (rowIsInCurrentRowset(firstRowInRowset_
2532: + currentRowInRowset_ - 1, scrollOrientation_prior__)) {
2533: isValidCursorPosition_ = true;
2534: currentRowInRowset_--;
2535: } else {
2536: checkAndThrowReceivedQueryTerminatingException();
2537: isValidCursorPosition_ = getPreviousRowset();
2538: }
2539:
2540: if (isValidCursorPosition_) {
2541: updateColumnInfoFromCache();
2542: // check if there is a non-null SQLCA for the row for rowset cursors
2543: checkRowsetSqlca();
2544: if (isAfterLast_) {
2545: isLast_ = true;
2546: }
2547: isAfterLast_ = false;
2548: } else {
2549: return isValidCursorPosition_;
2550: }
2551:
2552: if (sensitivity_ != sensitivity_sensitive_dynamic__
2553: && maxRows_ > 0
2554: && (firstRowInRowset_ + currentRowInRowset_ > maxRows_)) {
2555: isValidCursorPosition_ = false;
2556: }
2557: // auto-close result set if this is the last row from server and return false
2558: return isValidCursorPosition_;
2559: }
2560:
2561: public void setFetchDirection(int direction) throws SQLException {
2562: try {
2563: synchronized (connection_) {
2564: if (agent_.loggingEnabled()) {
2565: agent_.logWriter_.traceEntry(this ,
2566: "setFetchDirection", direction);
2567: }
2568: checkForClosedResultSet();
2569: checkThatResultSetTypeIsScrollable();
2570:
2571: switch (direction) {
2572: case java.sql.ResultSet.FETCH_FORWARD:
2573: case java.sql.ResultSet.FETCH_REVERSE:
2574: case java.sql.ResultSet.FETCH_UNKNOWN:
2575: fetchDirection_ = direction;
2576: break;
2577: default:
2578: throw new SqlException(agent_.logWriter_,
2579: new ClientMessageId(
2580: SQLState.INVALID_FETCH_DIRECTION),
2581: new Integer(direction));
2582: }
2583: }
2584: } catch (SqlException se) {
2585: throw se.getSQLException();
2586: }
2587: }
2588:
2589: public int getFetchDirection() throws SQLException {
2590: try {
2591: checkForClosedResultSet();
2592: if (agent_.loggingEnabled()) {
2593: agent_.logWriter_.traceExit(this , "getFetchDirection",
2594: fetchDirection_);
2595: }
2596: return fetchDirection_;
2597: } catch (SqlException se) {
2598: throw se.getSQLException();
2599: }
2600: }
2601:
2602: public void setFetchSize(int rows) throws SQLException {
2603: try {
2604: synchronized (connection_) {
2605: if (agent_.loggingEnabled()) {
2606: agent_.logWriter_.traceEntry(this , "setFetchSize",
2607: rows);
2608: }
2609: checkForClosedResultSet();
2610: if (rows < 0 || (maxRows_ != 0 && rows > maxRows_)) {
2611: throw new SqlException(agent_.logWriter_,
2612: new ClientMessageId(
2613: SQLState.INVALID_FETCH_SIZE),
2614: new Integer(rows)).getSQLException();
2615: }
2616: setFetchSize_(rows);
2617: }
2618: } catch (SqlException se) {
2619: throw se.getSQLException();
2620: }
2621: }
2622:
2623: public int getFetchSize() throws SQLException {
2624: try {
2625: if (agent_.loggingEnabled()) {
2626: agent_.logWriter_.traceExit(this , "getFetchSize",
2627: fetchSize_);
2628: }
2629: checkForClosedResultSet();
2630: return suggestedFetchSize_;
2631: } catch (SqlException se) {
2632: throw se.getSQLException();
2633: }
2634: }
2635:
2636: public int getType() throws SQLException {
2637: try {
2638: if (agent_.loggingEnabled()) {
2639: agent_.logWriter_.traceExit(this , "getType",
2640: resultSetType_);
2641: }
2642: checkForClosedResultSet();
2643: return resultSetType_;
2644: } catch (SqlException se) {
2645: throw se.getSQLException();
2646: }
2647: }
2648:
2649: public int getConcurrency() throws SQLException {
2650: try {
2651: if (agent_.loggingEnabled()) {
2652: agent_.logWriter_.traceExit(this , "getConcurrency",
2653: resultSetConcurrency_);
2654: }
2655: checkForClosedResultSet();
2656: return resultSetConcurrency_;
2657: } catch (SqlException se) {
2658: throw se.getSQLException();
2659: }
2660: }
2661:
2662: //----------------------------- Updates --------------------------------------
2663:
2664: public boolean rowUpdated() throws SQLException {
2665: try {
2666: checkForClosedResultSet();
2667: checkPositionedOnPlainRow();
2668:
2669: boolean rowUpdated = cursor_.getIsRowUpdated();
2670:
2671: if (agent_.loggingEnabled()) {
2672: agent_.logWriter_.traceExit(this , "rowUpdated",
2673: rowUpdated);
2674: }
2675: return rowUpdated;
2676: } catch (SqlException se) {
2677: throw se.getSQLException();
2678: }
2679: }
2680:
2681: public boolean rowInserted() throws SQLException {
2682: try {
2683: checkForClosedResultSet();
2684: checkPositionedOnPlainRow();
2685:
2686: boolean rowInserted = false;
2687:
2688: // Not implemented for any result set type,
2689: // so it always returns false.
2690:
2691: if (agent_.loggingEnabled()) {
2692: agent_.logWriter_.traceExit(this , "rowInserted",
2693: rowInserted);
2694: }
2695: return rowInserted;
2696: } catch (SqlException se) {
2697: throw se.getSQLException();
2698: }
2699: }
2700:
2701: public boolean rowDeleted() throws SQLException {
2702: try {
2703: checkForClosedResultSet();
2704: checkPositionedOnPlainRow();
2705:
2706: boolean rowDeleted = (resultSetType_ == ResultSet.TYPE_SCROLL_INSENSITIVE) ? cursor_
2707: .getIsUpdateDeleteHole()
2708: : false;
2709:
2710: if (agent_.loggingEnabled()) {
2711: agent_.logWriter_.traceExit(this , "rowDeleted",
2712: rowDeleted);
2713: }
2714: return rowDeleted;
2715: } catch (SqlException se) {
2716: throw se.getSQLException();
2717: }
2718: }
2719:
2720: // --------------------------- update column methods -------------------------
2721:
2722: public void updateNull(int column) throws SQLException {
2723: try {
2724: synchronized (connection_) {
2725: if (agent_.loggingEnabled()) {
2726: agent_.logWriter_.traceEntry(this , "updateNull",
2727: column);
2728: }
2729: checkUpdatePreconditions(column, "updateNull");
2730: if (!resultSetMetaData_.nullable_[column - 1]) {
2731: throw new SqlException(agent_.logWriter_,
2732: new ClientMessageId(
2733: SQLState.LANG_NULL_INTO_NON_NULL),
2734: new Integer(column));
2735: }
2736: updateColumn(column, null);
2737: }
2738: } catch (SqlException se) {
2739: throw se.getSQLException();
2740: }
2741: }
2742:
2743: public void updateBoolean(int column, boolean x)
2744: throws SQLException {
2745: try {
2746: synchronized (connection_) {
2747: if (agent_.loggingEnabled()) {
2748: agent_.logWriter_.traceEntry(this , "updateBoolean",
2749: column, x);
2750: }
2751: checkUpdatePreconditions(column, "updateBoolean");
2752: updateColumn(column, agent_.crossConverters_.setObject(
2753: resultSetMetaData_.types_[column - 1], x));
2754: }
2755: } catch (SqlException se) {
2756: throw se.getSQLException();
2757: }
2758: }
2759:
2760: public void updateByte(int column, byte x) throws SQLException {
2761: try {
2762: synchronized (connection_) {
2763: if (agent_.loggingEnabled()) {
2764: agent_.logWriter_.traceEntry(this , "updateByte",
2765: column, x);
2766: }
2767: checkUpdatePreconditions(column, "updateByte");
2768: updateColumn(column, agent_.crossConverters_.setObject(
2769: resultSetMetaData_.types_[column - 1], x));
2770: }
2771: } catch (SqlException se) {
2772: throw se.getSQLException();
2773: }
2774: }
2775:
2776: public void updateShort(int column, short x) throws SQLException {
2777: try {
2778: synchronized (connection_) {
2779: if (agent_.loggingEnabled()) {
2780: agent_.logWriter_.traceEntry(this , "updateShort",
2781: column, x);
2782: }
2783: checkUpdatePreconditions(column, "updateShort");
2784: updateColumn(column, agent_.crossConverters_.setObject(
2785: resultSetMetaData_.types_[column - 1], x));
2786: }
2787: } catch (SqlException se) {
2788: throw se.getSQLException();
2789: }
2790: }
2791:
2792: public void updateInt(int column, int x) throws SQLException {
2793: try {
2794: synchronized (connection_) {
2795: if (agent_.loggingEnabled()) {
2796: agent_.logWriter_.traceEntry(this , "updateInt",
2797: column, x);
2798: }
2799: checkUpdatePreconditions(column, "updateInt");
2800: updateColumn(column, agent_.crossConverters_.setObject(
2801: resultSetMetaData_.types_[column - 1], x));
2802: }
2803: } catch (SqlException se) {
2804: throw se.getSQLException();
2805: }
2806: }
2807:
2808: public void updateLong(int column, long x) throws SQLException {
2809: try {
2810: synchronized (connection_) {
2811: if (agent_.loggingEnabled()) {
2812: agent_.logWriter_.traceEntry(this , "updateLong",
2813: column, x);
2814: }
2815: checkUpdatePreconditions(column, "updateLong");
2816: updateColumn(column, agent_.crossConverters_.setObject(
2817: resultSetMetaData_.types_[column - 1], x));
2818: }
2819: } catch (SqlException se) {
2820: throw se.getSQLException();
2821: }
2822: }
2823:
2824: public void updateFloat(int column, float x) throws SQLException {
2825: try {
2826: synchronized (connection_) {
2827: if (agent_.loggingEnabled()) {
2828: agent_.logWriter_.traceEntry(this , "updateFloat",
2829: column, x);
2830: }
2831: checkUpdatePreconditions(column, "updateFloat");
2832: updateColumn(column, agent_.crossConverters_.setObject(
2833: resultSetMetaData_.types_[column - 1], x));
2834: }
2835: } catch (SqlException se) {
2836: throw se.getSQLException();
2837: }
2838: }
2839:
2840: public void updateDouble(int column, double x) throws SQLException {
2841: try {
2842: synchronized (connection_) {
2843: if (agent_.loggingEnabled()) {
2844: agent_.logWriter_.traceEntry(this , "updateDouble",
2845: column, x);
2846: }
2847: checkUpdatePreconditions(column, "updateDouble");
2848: updateColumn(column, agent_.crossConverters_.setObject(
2849: resultSetMetaData_.types_[column - 1], x));
2850: }
2851: } catch (SqlException se) {
2852: throw se.getSQLException();
2853: }
2854: }
2855:
2856: public void updateBigDecimal(int column, java.math.BigDecimal x)
2857: throws SQLException {
2858: try {
2859: synchronized (connection_) {
2860: if (agent_.loggingEnabled()) {
2861: agent_.logWriter_.traceEntry(this ,
2862: "updateBigDecimal", column, x);
2863: }
2864: checkUpdatePreconditions(column, "updateBigDecimal");
2865: updateColumn(column, agent_.crossConverters_.setObject(
2866: resultSetMetaData_.types_[column - 1], x));
2867: }
2868: } catch (SqlException se) {
2869: throw se.getSQLException();
2870: }
2871: }
2872:
2873: public void updateDate(int column, java.sql.Date x)
2874: throws SQLException {
2875: try {
2876: synchronized (connection_) {
2877: if (agent_.loggingEnabled()) {
2878: agent_.logWriter_.traceEntry(this , "updateDate",
2879: column, x);
2880: }
2881: checkUpdatePreconditions(column, "updateDate");
2882: updateColumn(column, agent_.crossConverters_.setObject(
2883: resultSetMetaData_.types_[column - 1], x));
2884: }
2885: } catch (SqlException se) {
2886: throw se.getSQLException();
2887: }
2888: }
2889:
2890: public void updateTime(int column, java.sql.Time x)
2891: throws SQLException {
2892: try {
2893: synchronized (connection_) {
2894: if (agent_.loggingEnabled()) {
2895: agent_.logWriter_.traceEntry(this , "updateTime",
2896: column, x);
2897: }
2898: checkUpdatePreconditions(column, "updateTime");
2899: updateColumn(column, agent_.crossConverters_.setObject(
2900: resultSetMetaData_.types_[column - 1], x));
2901: }
2902: } catch (SqlException se) {
2903: throw se.getSQLException();
2904: }
2905: }
2906:
2907: public void updateTimestamp(int column, java.sql.Timestamp x)
2908: throws SQLException {
2909: try {
2910: synchronized (connection_) {
2911: if (agent_.loggingEnabled()) {
2912: agent_.logWriter_.traceEntry(this ,
2913: "updateTimestamp", column, x);
2914: }
2915: checkUpdatePreconditions(column, "updateTimestamp");
2916: updateColumn(column, agent_.crossConverters_.setObject(
2917: resultSetMetaData_.types_[column - 1], x));
2918: }
2919: } catch (SqlException se) {
2920: throw se.getSQLException();
2921: }
2922: }
2923:
2924: public void updateString(int column, String x) throws SQLException {
2925: try {
2926: synchronized (connection_) {
2927: if (agent_.loggingEnabled()) {
2928: agent_.logWriter_.traceEntry(this , "updateString",
2929: column, x);
2930: }
2931: checkUpdatePreconditions(column, "updateString");
2932: updateColumn(column, agent_.crossConverters_.setObject(
2933: resultSetMetaData_.types_[column - 1], x));
2934: }
2935: } catch (SqlException se) {
2936: throw se.getSQLException();
2937: }
2938: }
2939:
2940: public void updateBytes(int column, byte x[]) throws SQLException {
2941: try {
2942: synchronized (connection_) {
2943: if (agent_.loggingEnabled()) {
2944: agent_.logWriter_.traceEntry(this , "updateBytes",
2945: column, x);
2946: }
2947: checkUpdatePreconditions(column, "updateBytes");
2948: updateColumn(column, agent_.crossConverters_.setObject(
2949: resultSetMetaData_.types_[column - 1], x));
2950: }
2951: } catch (SqlException se) {
2952: throw se.getSQLException();
2953: }
2954: }
2955:
2956: public void updateBinaryStream(int column, java.io.InputStream x,
2957: int length) throws SQLException {
2958: try {
2959: synchronized (connection_) {
2960: if (agent_.loggingEnabled()) {
2961: agent_.logWriter_.traceEntry(this , "", column, x,
2962: length);
2963: }
2964: checkUpdatePreconditions(column, "updateBinaryStream");
2965: updateColumn(column, agent_.crossConverters_
2966: .setObjectFromBinaryStream(
2967: resultSetMetaData_.types_[column - 1],
2968: x, length));
2969: }
2970: } catch (SqlException se) {
2971: throw se.getSQLException();
2972: }
2973: }
2974:
2975: public void updateAsciiStream(int column, java.io.InputStream x,
2976: int length) throws SQLException {
2977: try {
2978: synchronized (connection_) {
2979: if (agent_.loggingEnabled()) {
2980: agent_.logWriter_.traceEntry(this ,
2981: "updateAsciiStream", column, x, length);
2982: }
2983: checkUpdatePreconditions(column, "updateAsciiStream");
2984: updateColumn(column, agent_.crossConverters_
2985: .setObjectFromCharacterStream(
2986: resultSetMetaData_.types_[column - 1],
2987: x, "US-ASCII", length));
2988: }
2989: } catch (SqlException se) {
2990: throw se.getSQLException();
2991: }
2992: }
2993:
2994: public void updateCharacterStream(int column, java.io.Reader x,
2995: int length) throws SQLException {
2996: try {
2997: synchronized (connection_) {
2998: if (agent_.loggingEnabled()) {
2999: agent_.logWriter_.traceEntry(this ,
3000: "updateCharacterStream", column, x, length);
3001: }
3002: checkUpdatePreconditions(column,
3003: "updateCharacterStream");
3004: updateColumn(column, agent_.crossConverters_.setObject(
3005: resultSetMetaData_.types_[column - 1], x,
3006: length));
3007: }
3008: } catch (SqlException se) {
3009: throw se.getSQLException();
3010: }
3011: }
3012:
3013: public void updateObject(int column, Object x, int scale)
3014: throws SQLException {
3015: try {
3016: synchronized (connection_) {
3017: if (agent_.loggingEnabled()) {
3018: agent_.logWriter_.traceEntry(this , "updateObject",
3019: column, x, scale);
3020: }
3021: checkUpdatePreconditions(column, "updateObject");
3022: updateColumn(column, agent_.crossConverters_.setObject(
3023: resultSetMetaData_.types_[column - 1], x));
3024: }
3025: } catch (SqlException se) {
3026: throw se.getSQLException();
3027: }
3028: }
3029:
3030: public void updateObject(int column, Object x) throws SQLException {
3031: try {
3032: synchronized (connection_) {
3033: if (agent_.loggingEnabled()) {
3034: agent_.logWriter_.traceEntry(this , "updateObject",
3035: column, x);
3036: }
3037: checkUpdatePreconditions(column, "updateObject");
3038: updateColumn(column, agent_.crossConverters_.setObject(
3039: resultSetMetaData_.types_[column - 1], x));
3040: }
3041: } catch (SqlException se) {
3042: throw se.getSQLException();
3043: }
3044: }
3045:
3046: public void updateNCharacterStream(int columnIndex, Reader x)
3047: throws SQLException {
3048: throw jdbc3MethodNotSupported();
3049: }
3050:
3051: public void updateNClob(int columnIndex, Reader reader)
3052: throws SQLException {
3053: throw jdbc3MethodNotSupported();
3054: }
3055:
3056: // ---------------------- update on column name methods ----------------------
3057:
3058: public void updateNull(String columnName) throws SQLException {
3059: try {
3060: if (agent_.loggingEnabled()) {
3061: agent_.logWriter_.traceEntry(this , "updateNull",
3062: columnName);
3063: }
3064: updateNull(findColumnX(columnName));
3065: } catch (SqlException se) {
3066: throw se.getSQLException();
3067: }
3068: }
3069:
3070: public void updateBoolean(String columnName, boolean x)
3071: throws SQLException {
3072: try {
3073: if (agent_.loggingEnabled()) {
3074: agent_.logWriter_.traceEntry(this , "updateBoolean",
3075: columnName, x);
3076: }
3077: updateBoolean(findColumnX(columnName), x);
3078: } catch (SqlException se) {
3079: throw se.getSQLException();
3080: }
3081: }
3082:
3083: public void updateByte(String columnName, byte x)
3084: throws SQLException {
3085: try {
3086: if (agent_.loggingEnabled()) {
3087: agent_.logWriter_.traceEntry(this , "updateByte",
3088: columnName, x);
3089: }
3090: updateByte(findColumnX(columnName), x);
3091: } catch (SqlException se) {
3092: throw se.getSQLException();
3093: }
3094: }
3095:
3096: public void updateShort(String columnName, short x)
3097: throws SQLException {
3098: try {
3099: if (agent_.loggingEnabled()) {
3100: agent_.logWriter_.traceEntry(this , "updateShort",
3101: columnName, x);
3102: }
3103: updateShort(findColumnX(columnName), x);
3104: } catch (SqlException se) {
3105: throw se.getSQLException();
3106: }
3107: }
3108:
3109: public void updateInt(String columnName, int x) throws SQLException {
3110: try {
3111: if (agent_.loggingEnabled()) {
3112: agent_.logWriter_.traceEntry(this , "updateInt",
3113: columnName, x);
3114: }
3115: updateInt(findColumnX(columnName), x);
3116: } catch (SqlException se) {
3117: throw se.getSQLException();
3118: }
3119: }
3120:
3121: public void updateLong(String columnName, long x)
3122: throws SQLException {
3123: try {
3124: if (agent_.loggingEnabled()) {
3125: agent_.logWriter_.traceEntry(this , "updateLong",
3126: columnName, x);
3127: }
3128: updateLong(findColumnX(columnName), x);
3129: } catch (SqlException se) {
3130: throw se.getSQLException();
3131: }
3132: }
3133:
3134: public void updateFloat(String columnName, float x)
3135: throws SQLException {
3136: try {
3137: if (agent_.loggingEnabled()) {
3138: agent_.logWriter_.traceEntry(this , "updateFloat",
3139: columnName, x);
3140: }
3141: updateFloat(findColumnX(columnName), x);
3142: } catch (SqlException se) {
3143: throw se.getSQLException();
3144: }
3145: }
3146:
3147: public void updateDouble(String columnName, double x)
3148: throws SQLException {
3149: try {
3150: if (agent_.loggingEnabled()) {
3151: agent_.logWriter_.traceEntry(this , "updateDouble",
3152: columnName, x);
3153: }
3154: updateDouble(findColumnX(columnName), x);
3155: } catch (SqlException se) {
3156: throw se.getSQLException();
3157: }
3158: }
3159:
3160: public void updateBigDecimal(String columnName,
3161: java.math.BigDecimal x) throws SQLException {
3162: try {
3163: if (agent_.loggingEnabled()) {
3164: agent_.logWriter_.traceEntry(this , "updateBigDecimal",
3165: columnName, x);
3166: }
3167: updateBigDecimal(findColumnX(columnName), x);
3168: } catch (SqlException se) {
3169: throw se.getSQLException();
3170: }
3171: }
3172:
3173: public void updateDate(String columnName, java.sql.Date x)
3174: throws SQLException {
3175: try {
3176: if (agent_.loggingEnabled()) {
3177: agent_.logWriter_.traceEntry(this , "updateDate",
3178: columnName, x);
3179: }
3180: updateDate(findColumnX(columnName), x);
3181: } catch (SqlException se) {
3182: throw se.getSQLException();
3183: }
3184: }
3185:
3186: public void updateTime(String columnName, java.sql.Time x)
3187: throws SQLException {
3188: try {
3189: if (agent_.loggingEnabled()) {
3190: agent_.logWriter_.traceEntry(this , "updateTime",
3191: columnName, x);
3192: }
3193: updateTime(findColumnX(columnName), x);
3194: } catch (SqlException se) {
3195: throw se.getSQLException();
3196: }
3197: }
3198:
3199: public void updateTimestamp(String columnName, java.sql.Timestamp x)
3200: throws SQLException {
3201: try {
3202: if (agent_.loggingEnabled()) {
3203: agent_.logWriter_.traceEntry(this , "updateTimestamp",
3204: columnName, x);
3205: }
3206: updateTimestamp(findColumnX(columnName), x);
3207: } catch (SqlException se) {
3208: throw se.getSQLException();
3209: }
3210: }
3211:
3212: public void updateString(String columnName, String x)
3213: throws SQLException {
3214: try {
3215: if (agent_.loggingEnabled()) {
3216: agent_.logWriter_.traceEntry(this , "updateString",
3217: columnName, x);
3218: }
3219: updateString(findColumnX(columnName), x);
3220: } catch (SqlException se) {
3221: throw se.getSQLException();
3222: }
3223: }
3224:
3225: public void updateBytes(String columnName, byte x[])
3226: throws SQLException {
3227: try {
3228: if (agent_.loggingEnabled()) {
3229: agent_.logWriter_.traceEntry(this , "updateBytes",
3230: columnName, x);
3231: }
3232: updateBytes(findColumnX(columnName), x);
3233: } catch (SqlException se) {
3234: throw se.getSQLException();
3235: }
3236: }
3237:
3238: public void updateBinaryStream(String columnName,
3239: java.io.InputStream x, int length) throws SQLException {
3240: try {
3241: if (agent_.loggingEnabled()) {
3242: agent_.logWriter_.traceEntry(this ,
3243: "updateBinaryStream", columnName, x, length);
3244: }
3245: updateBinaryStream(findColumnX(columnName), x, length);
3246: } catch (SqlException se) {
3247: throw se.getSQLException();
3248: }
3249: }
3250:
3251: public void updateAsciiStream(String columnName,
3252: java.io.InputStream x, int length) throws SQLException {
3253: try {
3254: if (agent_.loggingEnabled()) {
3255: agent_.logWriter_.traceEntry(this , "updateAsciiStream",
3256: columnName, x, length);
3257: }
3258: updateAsciiStream(findColumnX(columnName), x, length);
3259: } catch (SqlException se) {
3260: throw se.getSQLException();
3261: }
3262: }
3263:
3264: public void updateCharacterStream(String columnName,
3265: java.io.Reader x, int length) throws SQLException {
3266: try {
3267: if (agent_.loggingEnabled()) {
3268: agent_.logWriter_.traceEntry(this ,
3269: "updateCharacterStream", columnName, x, length);
3270: }
3271: updateCharacterStream(findColumnX(columnName), x, length);
3272: } catch (SqlException se) {
3273: throw se.getSQLException();
3274: }
3275: }
3276:
3277: public void updateObject(String columnName, Object x, int scale)
3278: throws SQLException {
3279: try {
3280: if (agent_.loggingEnabled()) {
3281: agent_.logWriter_.traceEntry(this , "updateObject",
3282: columnName, x, scale);
3283: }
3284: updateObject(findColumnX(columnName), x, scale);
3285: } catch (SqlException se) {
3286: throw se.getSQLException();
3287: }
3288: }
3289:
3290: public void updateObject(String columnName, Object x)
3291: throws SQLException {
3292: try {
3293: if (agent_.loggingEnabled()) {
3294: agent_.logWriter_.traceEntry(this , "updateObject",
3295: columnName, x);
3296: }
3297: updateObject(findColumnX(columnName), x);
3298: } catch (SqlException se) {
3299: throw se.getSQLException();
3300: }
3301: }
3302:
3303: public void updateNCharacterStream(String columnName, Reader x)
3304: throws SQLException {
3305: throw jdbc3MethodNotSupported();
3306: }
3307:
3308: public void updateNClob(String columnName, Reader reader)
3309: throws SQLException {
3310: throw jdbc3MethodNotSupported();
3311: }
3312:
3313: // ---------------------------------------------------------------------------
3314:
3315: public void insertRow() throws SQLException {
3316: try {
3317: synchronized (connection_) {
3318: if (agent_.loggingEnabled()) {
3319: agent_.logWriter_.traceEntry(this , "insertRow");
3320: }
3321: insertRowX();
3322: }
3323: } catch (SqlException se) {
3324: throw se.getSQLException();
3325: }
3326: }
3327:
3328: private void insertRowX() throws SqlException {
3329: checkForClosedResultSet();
3330: checkForUpdatableResultSet("insertRow");
3331: if (isOnCurrentRow_) {
3332: throw new SqlException(
3333: agent_.logWriter_,
3334: new ClientMessageId(
3335: SQLState.CURSOR_NOT_POSITIONED_ON_INSERT_ROW));
3336: }
3337:
3338: // if not on a valid row, then do not accept updateXXX calls
3339: if (!isValidCursorPosition_) {
3340: throw new SqlException(
3341: agent_.logWriter_,
3342: new ClientMessageId(
3343: SQLState.CURSOR_INVALID_OPERATION_AT_CURRENT_POSITION));
3344: }
3345:
3346: // User might not be updating all the updatable columns selected in the
3347: // select sql and hence every insertRow on the same ResultSet can be
3348: // potentially different than the previous one. Because of that, we
3349: // should get a new prepared statement to do inserts every time
3350: getPreparedStatementForInsert();
3351:
3352: // build the inputs array for the prepared statement for insert
3353: int paramNumber = 0;
3354: for (int i = 0; i < updatedColumns_.length; i++) {
3355: if (resultSetMetaData_.sqlxUpdatable_[i] == 1) {
3356: // Since user may choose not to update all the columns in the
3357: // select list, check first if the column has been updated
3358: if (columnUpdated_[i] == true) {
3359: paramNumber++;
3360:
3361: // column is updated either if the updatedColumns_ entry is not null,
3362: // or if the updatedColumns_ entry is null, but columnUpdated is
3363: // set to true, which means columns is updated to a null.
3364: if (updatedColumns_[i] != null
3365: || (updatedColumns_[i] == null && columnUpdated_[i])) {
3366: preparedStatementForInsert_.setInput(
3367: paramNumber, updatedColumns_[i]);
3368: }
3369: }
3370: }
3371: }
3372: try {
3373: insert();
3374: } catch (SqlException e) {
3375: throw e;
3376: }
3377: }
3378:
3379: public void updateRow() throws java.sql.SQLException {
3380: try {
3381: synchronized (connection_) {
3382: if (agent_.loggingEnabled()) {
3383: agent_.logWriter_.traceEntry(this , "updateRow");
3384: }
3385: // If updateXXX were issued on the row before updateRow and
3386: // the result set if forward only, then position the ResultSet
3387: // to right before the next row after updateRow.
3388: if (updateRowX()
3389: && (getType() == ResultSet.TYPE_FORWARD_ONLY)) {
3390: isValidCursorPosition_ = false;
3391: }
3392: }
3393: } catch (SqlException se) {
3394: throw se.getSQLException();
3395: }
3396: }
3397:
3398: //if no updateXXX were issued before this updateRow, then return false
3399: private boolean updateRowX() throws SqlException {
3400: checkForClosedResultSet();
3401:
3402: checkForUpdatableResultSet("updateRow");
3403:
3404: if (isOnInsertRow_) {
3405: throw new SqlException(agent_.logWriter_,
3406: new ClientMessageId(SQLState.NO_CURRENT_ROW));
3407: }
3408:
3409: //if not on a valid row, then do not accept updateXXX calls
3410: if (!isValidCursorPosition_)
3411: throw new SqlException(
3412: agent_.logWriter_,
3413: new ClientMessageId(
3414: SQLState.CURSOR_INVALID_OPERATION_AT_CURRENT_POSITION));
3415:
3416: // If no updateXXX has been called on this ResultSet object, then
3417: // updatedColumns_ will be null and hence no action required
3418: if (updatedColumns_ == null) {
3419: return false;
3420: }
3421:
3422: // updateXXX has been called on this ResultSet object, but check if it
3423: // has been called on the current row. If no column got updated on this
3424: // current row, then just return.
3425: boolean didAnyColumnGetUpdated = false;
3426: for (int i = 0; i < updatedColumns_.length; i++) {
3427: if (columnUpdated_[i]) {
3428: didAnyColumnGetUpdated = true;
3429: break;
3430: }
3431: }
3432: if (didAnyColumnGetUpdated == false)
3433: return false;
3434:
3435: // User might not be updating all the updatable columns selected in the
3436: // select sql and hence every updateRow on the same ResultSet can be
3437: // potentially different than the previous one. Because of that, we
3438: // should get a new prepared statement to do updates every time
3439: getPreparedStatementForUpdate();
3440:
3441: // build the inputs array for the prepared statement for update
3442: int paramNumber = 0;
3443: for (int i = 0; i < updatedColumns_.length; i++) {
3444: if (resultSetMetaData_.sqlxUpdatable_[i] == 1) {
3445: // Since user may choose not to update all the columns in the
3446: // select list, check first if the column has been updated
3447: if (columnUpdated_[i] == false)
3448: continue;
3449: paramNumber++;
3450:
3451: // column is updated either if the updatedColumns_ entry is not null,
3452: // or if the updatedColumns_ entry is null, but columnUpdated_ boolean is
3453: // set to true, which means columns is updated to a null.
3454: if (updatedColumns_[i] != null
3455: || (updatedColumns_[i] == null && columnUpdated_[i])) {
3456: preparedStatementForUpdate_.setInput(paramNumber,
3457: updatedColumns_[i]);
3458: } else {
3459: // Check if the original column is null. Calling CrossConverters.setObject on a null
3460: // column causes "Data Conversion" Exception.
3461: Object originalObj;
3462: try {
3463: originalObj = getObject(i + 1);
3464: } catch (SQLException se) {
3465: throw new SqlException(se);
3466: }
3467:
3468: if (originalObj == null) {
3469: preparedStatementForUpdate_.setInput(
3470: paramNumber, null);
3471: } else {
3472: preparedStatementForUpdate_.setInput(
3473: paramNumber,
3474: agent_.crossConverters_.setObject(
3475: resultSetMetaData_.types_[i],
3476: originalObj));
3477: }
3478: }
3479: }
3480: }
3481: // need to cancel updates if the actual update was not successful at the server.
3482: // alternative is to check for updateCount_ in "positionToCurrentRowAndUpdate".
3483: // cancelRowUpdates if updateCount_ != 1
3484: try {
3485: if (isRowsetCursor_
3486: || sensitivity_ == sensitivity_sensitive_dynamic__
3487: || sensitivity_ == sensitivity_sensitive_static__) {
3488: update();
3489: } else {
3490: positionToCurrentRowAndUpdate();
3491: }
3492: } finally {
3493: resetUpdatedColumns();
3494: }
3495:
3496: // Ensure the data is reset
3497: if (resultSetType_ == ResultSet.TYPE_SCROLL_INSENSITIVE) {
3498: if (preparedStatementForUpdate_.updateCount_ > 0) {
3499: // This causes a round-trip
3500: getAbsoluteRowset(absolutePosition_);
3501: }
3502: }
3503:
3504: return true;
3505: }
3506:
3507: public void deleteRow() throws java.sql.SQLException {
3508: try {
3509: synchronized (connection_) {
3510: if (agent_.loggingEnabled()) {
3511: agent_.logWriter_.traceEntry(this , "deleteRow");
3512: }
3513: deleteRowX();
3514: //the cursor is not positioned on the deleted row after deleteRow.
3515: //User needs to issue ResultSet.next to reposition the ResultSet
3516: //on a valid row
3517: isValidCursorPosition_ = false;
3518: }
3519: } catch (SqlException se) {
3520: throw se.getSQLException();
3521: }
3522: }
3523:
3524: private void deleteRowX() throws SqlException {
3525: checkForClosedResultSet();
3526:
3527: checkForUpdatableResultSet("deleteRow");
3528:
3529: // discard all previous updates
3530: resetUpdatedColumns();
3531:
3532: if (isOnInsertRow_) {
3533: throw new SqlException(agent_.logWriter_,
3534: new ClientMessageId(SQLState.NO_CURRENT_ROW));
3535: }
3536:
3537: if (preparedStatementForDelete_ == null) {
3538: getPreparedStatementForDelete();
3539: }
3540:
3541: if (isRowsetCursor_
3542: || sensitivity_ == sensitivity_sensitive_dynamic__
3543: || sensitivity_ == sensitivity_sensitive_static__) {
3544: delete();
3545: } else {
3546: positionToCurrentRowAndDelete();
3547: }
3548:
3549: if (resultSetType_ == java.sql.ResultSet.TYPE_FORWARD_ONLY) {
3550: cursor_.isUpdateDeleteHole_ = true;
3551: } else {
3552: if (preparedStatementForDelete_.updateCount_ > 0) {
3553:
3554: cursor_.isUpdateDeleteHoleCache_.set(
3555: (int) currentRowInRowset_, Cursor.ROW_IS_NULL);
3556: cursor_.isUpdateDeleteHole_ = ((Boolean) cursor_.isUpdateDeleteHoleCache_
3557: .get((int) currentRowInRowset_)).booleanValue();
3558: }
3559: }
3560: }
3561:
3562: public void refreshRow() throws SQLException {
3563: try {
3564: synchronized (connection_) {
3565: if (agent_.loggingEnabled()) {
3566: agent_.logWriter_.traceEntry(this , "refreshRow");
3567: }
3568: refreshRowX();
3569: }
3570: } catch (SqlException se) {
3571: throw se.getSQLException();
3572: }
3573: }
3574:
3575: private void refreshRowX() throws SqlException {
3576: checkForClosedResultSet();
3577: checkThatResultSetTypeIsScrollable();
3578: checkForUpdatableResultSet("refreshRow");
3579: if (isBeforeFirstX() || isAfterLastX() || isOnInsertRow_) {
3580: throw new SqlException(agent_.logWriter_,
3581: new ClientMessageId(SQLState.NO_CURRENT_ROW));
3582: }
3583:
3584: // this method does nothing if ResultSet is TYPE_SCROLL_INSENSITIVE
3585: if (resultSetType_ == java.sql.ResultSet.TYPE_SCROLL_SENSITIVE) {
3586: isValidCursorPosition_ = getRefreshRowset();
3587: try {
3588: cancelRowUpdates();
3589: } catch (SQLException sqle) {
3590: throw new SqlException(sqle);
3591: }
3592:
3593: unuseStreams();
3594:
3595: }
3596: }
3597:
3598: public void cancelRowUpdates() throws SQLException {
3599: try {
3600: synchronized (connection_) {
3601: if (agent_.loggingEnabled()) {
3602: agent_.logWriter_.traceEntry(this ,
3603: "cancelRowUpdates");
3604: }
3605: checkForClosedResultSet();
3606: checkForUpdatableResultSet("cancelRowUpdates");
3607: if (isOnInsertRow_) {
3608: throw new SqlException(
3609: agent_.logWriter_,
3610: new ClientMessageId(
3611: SQLState.CURSOR_NOT_POSITIONED_ON_INSERT_ROW));
3612: }
3613:
3614: // if not on a valid row, then do not accept cancelRowUpdates call
3615: if (!isValidCursorPosition_)
3616: throw new SqlException(
3617: agent_.logWriter_,
3618: new ClientMessageId(
3619: SQLState.CURSOR_INVALID_OPERATION_AT_CURRENT_POSITION));
3620: // Reset updated columns
3621: resetUpdatedColumns();
3622: }
3623: } catch (SqlException se) {
3624: throw se.getSQLException();
3625: }
3626: }
3627:
3628: public void moveToInsertRow() throws SQLException {
3629: try {
3630: synchronized (connection_) {
3631: if (agent_.loggingEnabled()) {
3632: agent_.logWriter_.traceEntry(this ,
3633: "moveToInsertRow");
3634: }
3635: checkForClosedResultSet();
3636: checkForUpdatableResultSet("moveToInsertRow");
3637:
3638: resetUpdatedColumnsForInsert();
3639:
3640: isOnInsertRow_ = true;
3641: isOnCurrentRow_ = false;
3642: isValidCursorPosition_ = true;
3643: }
3644: } catch (SqlException se) {
3645: throw se.getSQLException();
3646: }
3647: }
3648:
3649: public void moveToCurrentRow() throws SQLException {
3650: try {
3651: synchronized (connection_) {
3652: if (agent_.loggingEnabled()) {
3653: agent_.logWriter_.traceEntry(this ,
3654: "moveToCurrentRow");
3655: }
3656: checkForClosedResultSet();
3657: checkForUpdatableResultSet("moveToCurrentRow");
3658:
3659: moveToCurrentRowX();
3660: }
3661: } catch (SqlException se) {
3662: throw se.getSQLException();
3663: }
3664: }
3665:
3666: private void moveToCurrentRowX() throws SqlException {
3667: if (isOnInsertRow_) {
3668: resetUpdatedColumns();
3669: isOnInsertRow_ = false;
3670: isOnCurrentRow_ = true;
3671: if (currentRowInRowset_ > 0) {
3672: updateColumnInfoFromCache();
3673: }
3674: isValidCursorPosition_ = true;
3675: }
3676: }
3677:
3678: /**
3679: * Retrieves the <code>Statement</code> object that produced this
3680: * object, or <code>null</code> if the <code>ResultSet</code> was
3681: * not produced by a <code>Statement</code> object.
3682: *
3683: * @return the <code>Statement</code> that produced this object or
3684: * <code>null</code>
3685: * @exception SQLException if a database error occurs or the
3686: * result set is closed
3687: */
3688: public java.sql.Statement getStatement() throws SQLException {
3689: try {
3690: checkForClosedResultSet();
3691: } catch (SqlException se) {
3692: throw se.getSQLException();
3693: }
3694: if (agent_.loggingEnabled()) {
3695: agent_.logWriter_.traceExit(this , "getStatement",
3696: statement_);
3697: }
3698: return statement_;
3699: }
3700:
3701: //-------------------------- JDBC 3.0 ----------------------------------------
3702:
3703: public java.net.URL getURL(int columnIndex) throws SQLException {
3704: throw jdbc3MethodNotSupported();
3705: }
3706:
3707: public java.net.URL getURL(String columnName) throws SQLException {
3708: throw jdbc3MethodNotSupported();
3709: }
3710:
3711: public void updateRef(int columnIndex, java.sql.Ref x)
3712: throws SQLException {
3713: throw jdbc3MethodNotSupported();
3714: }
3715:
3716: public void updateRef(String columnName, java.sql.Ref x)
3717: throws SQLException {
3718: throw jdbc3MethodNotSupported();
3719: }
3720:
3721: public void updateBlob(int columnIndex, java.sql.Blob x)
3722: throws SQLException {
3723: throw jdbc3MethodNotSupported();
3724: }
3725:
3726: public void updateBlob(String columnName, java.sql.Blob x)
3727: throws SQLException {
3728: throw jdbc3MethodNotSupported();
3729: }
3730:
3731: public void updateClob(int columnIndex, java.sql.Clob x)
3732: throws SQLException {
3733: throw jdbc3MethodNotSupported();
3734: }
3735:
3736: public void updateClob(String columnName, java.sql.Clob x)
3737: throws SQLException {
3738: throw jdbc3MethodNotSupported();
3739: }
3740:
3741: public void updateArray(int columnIndex, java.sql.Array x)
3742: throws SQLException {
3743: throw jdbc3MethodNotSupported();
3744: }
3745:
3746: public void updateArray(String columnName, java.sql.Array x)
3747: throws SQLException {
3748: throw jdbc3MethodNotSupported();
3749: }
3750:
3751: public boolean repositionScrollableResultSetBeforeJDBC1PositionedUpdateDelete()
3752: throws SqlException {
3753: boolean repositionedCursor = false;
3754:
3755: // calculate the absolutePosition of the current row directly.
3756: long rowToFetch = getRowUncast() - absolutePosition_;
3757:
3758: // if rowToFetch is zero, already positioned on the current row
3759: if (rowToFetch != 0) {
3760: writePositioningFetch_(
3761: (generatedSection_ == null) ? statement_.section_
3762: : generatedSection_,
3763: scrollOrientation_relative__, rowToFetch);
3764: // adjust the absolute position on the client
3765: absolutePosition_ += rowToFetch;
3766: repositionedCursor = true;
3767: }
3768: return repositionedCursor;
3769: }
3770:
3771: //--------------------categorize the methods below -----------------
3772:
3773: public void flowPositioningFetch(int scrollOrientation,
3774: int rowToFetch) throws DisconnectException {
3775: // need the try-catch block here because agent_.beginWriteChain throws
3776: // an SqlException
3777: try {
3778: agent_.beginWriteChain(statement_);
3779:
3780: writePositioningFetch_(
3781: (generatedSection_ == null) ? statement_.section_
3782: : generatedSection_, scrollOrientation,
3783: rowToFetch);
3784:
3785: agent_.flow(statement_);
3786: readPositioningFetch_();
3787: agent_.endReadChain();
3788: } catch (SqlException e) {
3789: throw new DisconnectException(agent_, e);
3790: }
3791: }
3792:
3793: protected void positionToCurrentRowAndUpdate() throws SqlException {
3794: agent_.beginWriteChain(statement_);
3795:
3796: // calculate the position of the current row relative to the absolute position on server
3797: long currentRowPosRelativeToAbsoluteRowPos = getRowUncast()
3798: - absolutePosition_;
3799:
3800: // if currentRowPosRelativeToAbsoluteRowPos is zero, already on the current row
3801: // reposition only if a commit has been sent
3802: // do not reposition forward-only cursors
3803: if (resultSetType_ != java.sql.ResultSet.TYPE_FORWARD_ONLY
3804: && (currentRowPosRelativeToAbsoluteRowPos != 0 || (currentRowPosRelativeToAbsoluteRowPos == 0 && cursorUnpositionedOnServer_))) {
3805: writePositioningFetch_(
3806: (generatedSection_ == null) ? statement_.section_
3807: : generatedSection_,
3808: scrollOrientation_relative__,
3809: currentRowPosRelativeToAbsoluteRowPos);
3810: }
3811:
3812: // re-prepare the update statement if repreparing is needed after a commit.
3813: if (!preparedStatementForUpdate_.openOnServer_) {
3814: preparedStatementForUpdate_.materialPreparedStatement_
3815: .writePrepare_(preparedStatementForUpdate_.sql_,
3816: preparedStatementForUpdate_.section_);
3817: }
3818:
3819: try {
3820: writeUpdateRow(false);
3821: } catch (SQLException se) {
3822: throw new SqlException(se);
3823: }
3824:
3825: agent_.flow(statement_);
3826:
3827: // adjust the absolute position on the client
3828: absolutePosition_ += currentRowPosRelativeToAbsoluteRowPos;
3829:
3830: if (resultSetType_ != java.sql.ResultSet.TYPE_FORWARD_ONLY
3831: && (currentRowPosRelativeToAbsoluteRowPos != 0 || (currentRowPosRelativeToAbsoluteRowPos == 0 && cursorUnpositionedOnServer_))) {
3832: readPositioningFetch_();
3833: cursorUnpositionedOnServer_ = false;
3834: listenToUnitOfWork();
3835: }
3836:
3837: // read prepare replies if the update statement is re-prepared after a commit.
3838: if (!preparedStatementForUpdate_.openOnServer_) {
3839: preparedStatementForUpdate_.materialPreparedStatement_
3840: .readPrepare_();
3841: }
3842: readUpdateRow();
3843:
3844: agent_.endReadChain();
3845: }
3846:
3847: protected void insert() throws SqlException {
3848: agent_.beginWriteChain(statement_);
3849:
3850: // re-prepare the insert statement if repreparing is needed after a commit.
3851: if (!preparedStatementForInsert_.openOnServer_) {
3852: preparedStatementForInsert_.materialPreparedStatement_
3853: .writePrepare_(preparedStatementForInsert_.sql_,
3854: preparedStatementForInsert_.section_);
3855: }
3856:
3857: try {
3858: writeInsertRow(false);
3859: } catch (SQLException se) {
3860: throw new SqlException(se);
3861: }
3862:
3863: agent_.flow(statement_);
3864:
3865: // read prepare replies if the update statement is re-prepared after a commit.
3866: if (!preparedStatementForInsert_.openOnServer_) {
3867: preparedStatementForInsert_.materialPreparedStatement_
3868: .readPrepare_();
3869: }
3870:
3871: readInsertRow();
3872:
3873: agent_.endReadChain();
3874: }
3875:
3876: protected void update() throws SqlException {
3877: agent_.beginWriteChain(statement_);
3878:
3879: // re-prepare the update statement if repreparing is needed after a commit.
3880: if (!preparedStatementForUpdate_.openOnServer_) {
3881: preparedStatementForUpdate_.materialPreparedStatement_
3882: .writePrepare_(preparedStatementForUpdate_.sql_,
3883: preparedStatementForUpdate_.section_);
3884: }
3885:
3886: if (isRowsetCursor_) {
3887: try {
3888: preparedStatementForUpdate_.setInt(
3889: updatedColumns_.length + 1,
3890: (int) (currentRowInRowset_ + 1));
3891: } catch (SQLException se) {
3892: throw new SqlException(se);
3893: }
3894: }
3895:
3896: boolean chainAutoCommit = connection_
3897: .willAutoCommitGenerateFlow();
3898: try {
3899: writeUpdateRow(chainAutoCommit);
3900: } catch (SQLException se) {
3901: throw new SqlException(se);
3902: }
3903: if (chainAutoCommit) {
3904: connection_.writeCommit();
3905: }
3906:
3907: agent_.flow(statement_);
3908:
3909: // read prepare replies if the update statement is re-prepared after a commit.
3910: if (!preparedStatementForUpdate_.openOnServer_) {
3911: preparedStatementForUpdate_.materialPreparedStatement_
3912: .readPrepare_();
3913: }
3914:
3915: readUpdateRow();
3916:
3917: if (chainAutoCommit) {
3918: connection_.readCommit();
3919: }
3920: agent_.endReadChain();
3921: }
3922:
3923: protected void positionToCurrentRowAndDelete() throws SqlException {
3924: agent_.beginWriteChain(statement_);
3925:
3926: // calculate the position of the current row relative to the absolute position on server
3927: long currentRowPosRelativeToAbsoluteRowPos = getRowUncast()
3928: - absolutePosition_;
3929:
3930: // if rowToFetch is zero, already positioned on the current row
3931: // do not reposition forward-only cursors.
3932: if (resultSetType_ != java.sql.ResultSet.TYPE_FORWARD_ONLY
3933: && (currentRowPosRelativeToAbsoluteRowPos != 0 || (currentRowPosRelativeToAbsoluteRowPos == 0 && cursorUnpositionedOnServer_))) {
3934: writePositioningFetch_(
3935: (generatedSection_ == null) ? statement_.section_
3936: : generatedSection_,
3937: scrollOrientation_relative__,
3938: currentRowPosRelativeToAbsoluteRowPos);
3939: }
3940:
3941: // re-prepare the update statement if repreparing is needed after a commit.
3942: if (!preparedStatementForDelete_.openOnServer_) {
3943: preparedStatementForDelete_.materialPreparedStatement_
3944: .writePrepare_(preparedStatementForDelete_.sql_,
3945: preparedStatementForDelete_.section_);
3946: }
3947:
3948: try {
3949: writeDeleteRow();
3950: } catch (SQLException sqle) {
3951: throw new SqlException(sqle);
3952: }
3953:
3954: agent_.flow(statement_);
3955:
3956: // adjust the absolute position on the client.
3957: absolutePosition_ += currentRowPosRelativeToAbsoluteRowPos;
3958:
3959: if (resultSetType_ != java.sql.ResultSet.TYPE_FORWARD_ONLY
3960: && (currentRowPosRelativeToAbsoluteRowPos != 0 || (currentRowPosRelativeToAbsoluteRowPos == 0 && cursorUnpositionedOnServer_))) {
3961: readPositioningFetch_();
3962: cursorUnpositionedOnServer_ = false;
3963: listenToUnitOfWork();
3964: }
3965:
3966: // read prepare replies if the update statement is re-prepared after a commit.
3967: if (!preparedStatementForDelete_.openOnServer_) {
3968: preparedStatementForDelete_.materialPreparedStatement_
3969: .readPrepare_();
3970: }
3971: readDeleteRow();
3972:
3973: agent_.endReadChain();
3974: }
3975:
3976: protected void delete() throws SqlException {
3977: try {
3978: agent_.beginWriteChain(statement_);
3979:
3980: // re-prepare the update statement if repreparing is needed after a commit.
3981: if (!preparedStatementForDelete_.openOnServer_) {
3982: preparedStatementForDelete_.materialPreparedStatement_
3983: .writePrepare_(
3984: preparedStatementForDelete_.sql_,
3985: preparedStatementForDelete_.section_);
3986: }
3987:
3988: if (isRowsetCursor_) {
3989: preparedStatementForDelete_.setInt(1,
3990: (int) (currentRowInRowset_ + 1));
3991: }
3992:
3993: writeDeleteRow();
3994:
3995: if (connection_.autoCommit_) {
3996: connection_.writeAutoCommit();
3997: }
3998:
3999: agent_.flow(statement_);
4000:
4001: // read prepare replies if the update statement is re-prepared after a commit.
4002: if (!preparedStatementForDelete_.openOnServer_) {
4003: preparedStatementForDelete_.materialPreparedStatement_
4004: .readPrepare_();
4005: }
4006: readDeleteRow();
4007: if (connection_.autoCommit_) {
4008: connection_.readAutoCommit();
4009: }
4010: agent_.endReadChain();
4011: } catch (SQLException se) {
4012: throw new SqlException(se);
4013: }
4014: }
4015:
4016: // Resets all rowset related flags.
4017: // Called by getRowSet() from material layer.
4018: public void setRowsetAfterLastEvent() throws SqlException {
4019: firstRowInRowset_ = 0;
4020: lastRowInRowset_ = 0;
4021: absolutePosition_ = (maxRows_ == 0) ? rowCount_ + 1
4022: : maxRows_ + 1;
4023: currentRowInRowset_ = 0;
4024: rowsReceivedInCurrentRowset_ = 0;
4025: }
4026:
4027: public void setRowsetBeforeFirstEvent() throws SqlException {
4028: firstRowInRowset_ = 0;
4029: lastRowInRowset_ = 0;
4030: absolutePosition_ = 0;
4031: currentRowInRowset_ = -1;
4032: rowsReceivedInCurrentRowset_ = 0;
4033: }
4034:
4035: public void setRowsetNoRowsEvent() {
4036: rowCount_ = 0;
4037: firstRowInRowset_ = 0;
4038: lastRowInRowset_ = 0;
4039: absolutePosition_ = 0;
4040: currentRowInRowset_ = -1;
4041: rowsReceivedInCurrentRowset_ = 0;
4042: }
4043:
4044: private boolean isServersCursorPositionBeforeFirst()
4045: throws SqlException {
4046: return (isBeforeFirstX() && firstRowInRowset_ == 0
4047: && lastRowInRowset_ == 0 && absolutePosition_ == 0);
4048: }
4049:
4050: private boolean isServerCursorPositionAfterLast()
4051: throws SqlException {
4052: return (absolutePosition_ == (rowCount_ + 1));
4053: }
4054:
4055: public void setValidCursorPosition(boolean isValidCursorPosition) {
4056: isValidCursorPosition_ = isValidCursorPosition;
4057: }
4058:
4059: protected void moveToAfterLast() throws DisconnectException {
4060: flowPositioningFetch(ResultSet.scrollOrientation_after__, 0);
4061: }
4062:
4063: // Positions the cursor at before the first row.
4064: protected void moveToBeforeFirst() throws DisconnectException {
4065: flowPositioningFetch(ResultSet.scrollOrientation_before__, 0);
4066: }
4067:
4068: // analyze the error handling here, and whether or not can be pushed to common
4069: // can we make this the common layer fetch method
4070: // Called by the read/skip Fdoca bytes methods in the net
4071: // whenever data reads exhaust the internal buffer used by this reply
4072: public void flowFetch() throws DisconnectException, SqlException {
4073: agent_.beginWriteChain(statement_);
4074: writeFetch_((generatedSection_ == null) ? statement_.section_
4075: : generatedSection_);
4076: agent_.flow(statement_);
4077: readFetch_();
4078: agent_.endReadChain();
4079: }
4080:
4081: public void writeInsertRow(boolean chainedWritesFollowingSetLob)
4082: throws SQLException {
4083: try {
4084: preparedStatementForInsert_.materialPreparedStatement_
4085: .writeExecute_(
4086: preparedStatementForInsert_.section_,
4087: preparedStatementForInsert_.parameterMetaData_,
4088: preparedStatementForInsert_.parameters_,
4089: (preparedStatementForInsert_.parameterMetaData_ == null ? 0
4090: : preparedStatementForInsert_.parameterMetaData_
4091: .getColumnCount()), false, // false means we're not expecting output
4092: chainedWritesFollowingSetLob); // chaining after the execute
4093: } catch (SqlException se) {
4094: throw se.getSQLException();
4095: }
4096: }
4097:
4098: public void writeUpdateRow(boolean chainedWritesFollowingSetLob)
4099: throws SQLException {
4100: try {
4101: preparedStatementForUpdate_.materialPreparedStatement_
4102: .writeExecute_(
4103: preparedStatementForUpdate_.section_,
4104: preparedStatementForUpdate_.parameterMetaData_,
4105: preparedStatementForUpdate_.parameters_,
4106: preparedStatementForUpdate_.parameterMetaData_
4107: .getColumnCount(), false, // false means we're not expecting output
4108: chainedWritesFollowingSetLob); // chaining after the execute
4109: } catch (SqlException se) {
4110: throw se.getSQLException();
4111: }
4112: }
4113:
4114: public void writeDeleteRow() throws SQLException {
4115: try {
4116: if (isRowsetCursor_) {
4117: preparedStatementForDelete_.materialPreparedStatement_
4118: .writeExecute_(
4119: preparedStatementForDelete_.section_,
4120: preparedStatementForDelete_.parameterMetaData_,
4121: preparedStatementForDelete_.parameters_,
4122: preparedStatementForDelete_.parameterMetaData_
4123: .getColumnCount(), false, // false means we're not expecting output
4124: false); // false means we don't chain anything after the execute
4125: } else {
4126: preparedStatementForDelete_.materialPreparedStatement_
4127: .writeExecute_(
4128: preparedStatementForDelete_.section_,
4129: null, // do not need parameterMetaData since there is no input
4130: null, // no inputs
4131: 0, // number of input columns is 0 for positioned delete
4132: false, // false means we're not expecting output
4133: false); // false means we don't chain anything after the execute
4134: }
4135: } catch (SqlException se) {
4136: throw se.getSQLException();
4137: }
4138: }
4139:
4140: public void readInsertRow() throws DisconnectException,
4141: SqlException {
4142: preparedStatementForInsert_.materialPreparedStatement_
4143: .readExecute_();
4144: }
4145:
4146: public void readUpdateRow() throws DisconnectException,
4147: SqlException {
4148: preparedStatementForUpdate_.materialPreparedStatement_
4149: .readExecute_();
4150: accumulateWarning(preparedStatementForUpdate_.getSqlWarnings());
4151: }
4152:
4153: public void readDeleteRow() throws DisconnectException,
4154: SqlException {
4155: preparedStatementForDelete_.materialPreparedStatement_
4156: .readExecute_();
4157: accumulateWarning(preparedStatementForDelete_.getSqlWarnings());
4158: }
4159:
4160: //------------------material layer event callback methods-----------------------
4161:
4162: boolean listenToUnitOfWork_ = false;
4163:
4164: public void listenToUnitOfWork() {
4165: if (!listenToUnitOfWork_) {
4166: listenToUnitOfWork_ = true;
4167: connection_.CommitAndRollbackListeners_.put(this , null);
4168: }
4169: }
4170:
4171: public void completeLocalCommit(java.util.Iterator listenerIterator) {
4172: cursorUnpositionedOnServer_ = true;
4173: markAutoCommitted();
4174: if (!cursorHold_) {
4175: // only non-held cursors need to be closed at commit
4176: markClosed();
4177: nullOutReferenceInStatement();
4178: // remove from listener list
4179: listenerIterator.remove();
4180: listenToUnitOfWork_ = false;
4181: }
4182: }
4183:
4184: public void completeLocalRollback(
4185: java.util.Iterator listenerIterator) {
4186: markAutoCommitted();
4187: // all cursors need to be closed at rollback
4188: markClosed();
4189: nullOutReferenceInStatement();
4190: // remove from listener list
4191: listenerIterator.remove();
4192: listenToUnitOfWork_ = false;
4193: }
4194:
4195: private void nullOutReferenceInStatement() {
4196: if (statement_.resultSet_ == this ) {
4197: statement_.resultSet_ = null;
4198: }
4199: /*
4200: * Aug 10, 2005: Do we really only want to only null out the one resultSet?
4201: * The only time this method is called is from completeLocalCommit or
4202: * completeLocalRollback, both of which affect *all* ResultSets
4203: */
4204: if (statement_.resultSetList_ != null) {
4205: for (int i = 0; i < statement_.resultSetList_.length; i++) {
4206: if (statement_.resultSetList_[i] == this ) {
4207: statement_.resultSetList_[i] = null;
4208: }
4209: }
4210: }
4211: }
4212:
4213: /**
4214: * Mark this ResultSet as closed. The ResultSet will not be
4215: * removed from the commit and rollback listeners list in
4216: * <code>org.apache.derby.client.am.Connection</code>.
4217: */
4218: void markClosed() {
4219: markClosed(false);
4220: }
4221:
4222: /**
4223: * Mark this ResultSet as closed.
4224: *
4225: * @param removeListener if true the ResultSet will be removed
4226: * from the commit and rollback listeners list in
4227: * <code>org.apache.derby.client.am.Connection</code>.
4228: */
4229: void markClosed(boolean removeListener) {
4230: openOnClient_ = false;
4231: openOnServer_ = false;
4232: statement_.resetCursorNameAndRemoveFromWhereCurrentOfMappings(); // for SELECT...FOR UPDATE queries
4233: statement_.removeClientCursorNameFromCache();
4234: markPositionedUpdateDeletePreparedStatementsClosed();
4235: if (removeListener) {
4236: connection_.CommitAndRollbackListeners_.remove(this );
4237: }
4238: }
4239:
4240: /**
4241: * Mark this ResultSet as closed on the server.
4242: */
4243: public void markClosedOnServer() {
4244: openOnServer_ = false;
4245: }
4246:
4247: void markAutoCommitted() {
4248: autoCommitted_ = true;
4249: }
4250:
4251: // The query was ended at the server because all rows have been retrieved.
4252: public void earlyCloseComplete(Sqlca sqlca) {
4253: markClosedOnServer();
4254: queryTerminatingSqlca_ = sqlca;
4255: cursor_.setAllRowsReceivedFromServer(true);
4256: }
4257:
4258: public int completeSqlca(Sqlca sqlca) {
4259: if (sqlca == null) {
4260: return 0;
4261: }
4262: int sqlcode = sqlca.getSqlCode();
4263: if (sqlcode == 100 || sqlcode == 20237) {
4264: cursor_.setAllRowsReceivedFromServer(true);
4265: } else if (sqlcode < 0) {
4266: connection_.agent_
4267: .accumulateReadException(new SqlException(
4268: agent_.logWriter_, sqlca));
4269: } else if (sqlcode > 0) {
4270: accumulateWarning(new SqlWarning(agent_.logWriter_, sqlca));
4271: }
4272: return sqlcode;
4273: }
4274:
4275: // Set rowCount.
4276: public void setRowCountEvent(long rowCount)
4277: throws DisconnectException {
4278: // Only set the row count if it's unknown, to prevent clobbering of a valid value.
4279: if (rowCount_ == -1) {
4280: rowCount_ = rowCount;
4281: }
4282: }
4283:
4284: // This method will not work if e is chained.
4285: // It is assumed that e is a single warning and is not chained.
4286: public void accumulateWarning(SqlWarning e) {
4287: if (warnings_ == null) {
4288: warnings_ = e;
4289: } else {
4290: warnings_.setNextException(e);
4291: }
4292: }
4293:
4294: //-------------------------------helper methods-------------------------------
4295: protected boolean rowCountIsUnknown() {
4296: if (sensitivity_ == sensitivity_sensitive_dynamic__) {
4297: return false;
4298: } else {
4299: return rowCount_ == -1;
4300: }
4301: }
4302:
4303: protected boolean rowCountIsKnown() {
4304: return rowCount_ != -1;
4305: }
4306:
4307: private void updateColumn(int column, Object value) {
4308: if (updatedColumns_ == null) {
4309: updatedColumns_ = new Object[resultSetMetaData_.columns_];
4310: }
4311: if (columnUpdated_ == null) {
4312: columnUpdated_ = new boolean[resultSetMetaData_.columns_];
4313: }
4314:
4315: updatedColumns_[column - 1] = value;
4316: columnUpdated_[column - 1] = true;
4317: }
4318:
4319: /*
4320: * Builds the insert statement that will be used well calling insertRow
4321: *
4322: * If no values have been supplied for a column, it will be set
4323: * to the column's default value, if any.
4324: * If no default value had been defined, the default value of a
4325: * nullable column is set to NULL.
4326: */
4327: private String buildInsertString() throws SqlException {
4328: int column;
4329: boolean foundOneUpdatedColumnAlready = false;
4330:
4331: StringBuffer insertSQL = new StringBuffer("INSERT INTO ");
4332: StringBuffer valuesSQL = new StringBuffer("VALUES (");
4333:
4334: insertSQL.append(getTableName());
4335: insertSQL.append(" (");
4336:
4337: for (column = 1; column <= resultSetMetaData_.columns_; column++) {
4338: if (foundOneUpdatedColumnAlready) {
4339: insertSQL.append(",");
4340: valuesSQL.append(",");
4341: }
4342: //using quotes around the column name to preserve case sensitivity
4343: try {
4344: insertSQL.append(quoteSqlIdentifier(resultSetMetaData_
4345: .getColumnName(column)));
4346: } catch (SQLException sqle) {
4347: throw new SqlException(sqle);
4348: }
4349: if (columnUpdated_[column - 1]) {
4350: valuesSQL.append("?");
4351: } else {
4352: valuesSQL.append("DEFAULT");
4353: }
4354: foundOneUpdatedColumnAlready = true;
4355: }
4356:
4357: insertSQL.append(") ");
4358: valuesSQL.append(") ");
4359: insertSQL.append(valuesSQL.toString());
4360:
4361: return (insertSQL.toString());
4362: }
4363:
4364: private String buildUpdateString() throws SqlException {
4365: int column;
4366: int numColumns = 0;
4367:
4368: // For Derby, eg update t1 set c1=?, c2=? where current of cursorname
4369: boolean foundOneUpdatedColumnAlready = false;
4370: String updateString = "UPDATE " + getTableName() + " SET ";
4371:
4372: for (column = 1; column <= resultSetMetaData_.columns_; column++) {
4373: if (columnUpdated_[column - 1]) {
4374: if (foundOneUpdatedColumnAlready) {
4375: updateString += ",";
4376: }
4377: try {
4378: updateString += quoteSqlIdentifier(resultSetMetaData_
4379: .getColumnName(column))
4380: + " = ? ";
4381: } catch (SQLException sqle) {
4382: throw new SqlException(sqle);
4383: }
4384: numColumns++;
4385: foundOneUpdatedColumnAlready = true;
4386: }
4387: }
4388: if (foundOneUpdatedColumnAlready == false) //no columns updated on this row
4389: {
4390: return null;
4391: }
4392: updateString = updateString + " WHERE CURRENT OF "
4393: + getServerCursorName();
4394:
4395: if (isRowsetCursor_) {
4396: updateString += " FOR ROW ? OF ROWSET";
4397: }
4398:
4399: return updateString;
4400: }
4401:
4402: private String buildDeleteString() throws SqlException {
4403: String deleteString = "DELETE FROM ";
4404:
4405: // build the delete string using the server's cursor name
4406: deleteString += (getTableName() + " WHERE CURRENT OF \""
4407: + getServerCursorName() + "\"");
4408:
4409: if (isRowsetCursor_) {
4410: deleteString += " FOR ROW ? OF ROWSET";
4411: }
4412:
4413: return deleteString;
4414: }
4415:
4416: //Go through all the columns in the select list to see if we can find a
4417: //base table column and use that column's metadata to get the table name
4418: //But, it is possible to have a sql of the form
4419: //select 1,2 from t1 for update
4420: //This sql will not be a good candidate for updateXXX calls(both in embedded
4421: //and Network Server mode) since there is no updatable column in the select
4422: //list. But a user can use a sql like that to issue deleteRow. In Network
4423: //Server mode though, this sql will fail for deleteRow because none of the
4424: //columns are from base table and w/o a base table column, there is no way
4425: //to find the table name for delete
4426: private String getTableName() throws SqlException {
4427: String tableName = "";
4428: int baseTableColumn = 0;
4429: int totalColumns;
4430: try {
4431: totalColumns = resultSetMetaData_.getColumnCount();
4432: } catch (SQLException sqle) {
4433: throw new SqlException(sqle);
4434: }
4435: for (; baseTableColumn < totalColumns; baseTableColumn++) {
4436: if (resultSetMetaData_.sqlxBasename_[baseTableColumn] != null)
4437: break;
4438: }
4439:
4440: //if following true, then there are no base table columns in select list
4441: if (baseTableColumn == totalColumns)
4442: baseTableColumn = 0;
4443:
4444: //dervied column like select 2 from t1, has null schema and table name
4445: if (resultSetMetaData_.sqlxSchema_[baseTableColumn] != null
4446: && !resultSetMetaData_.sqlxSchema_[baseTableColumn]
4447: .equals("")) {
4448: tableName += quoteSqlIdentifier(resultSetMetaData_.sqlxSchema_[baseTableColumn])
4449: + ".";
4450: }
4451: if (resultSetMetaData_.sqlxBasename_[baseTableColumn] != null) {
4452: tableName += quoteSqlIdentifier(resultSetMetaData_.sqlxBasename_[baseTableColumn]);
4453: }
4454: return tableName;
4455: }
4456:
4457: private String quoteSqlIdentifier(String orgValue) {
4458: int i = 0, start = 0;
4459: String retValue = "";
4460: while ((i = orgValue.indexOf("\"", start) + 1) > 0) {
4461: retValue += orgValue.substring(start, i) + "\"";
4462: start = i;
4463: }
4464: retValue += orgValue.substring(start, orgValue.length());
4465: return "\"" + retValue + "\"";
4466: }
4467:
4468: private String getServerCursorName() throws SqlException {
4469: return statement_.section_.getServerCursorName();
4470: }
4471:
4472: private void getPreparedStatementForInsert() throws SqlException {
4473: // each column is associated with a tableName in the extended describe info.
4474: String insertString = buildInsertString();
4475:
4476: try {
4477: preparedStatementForInsert_ = (PreparedStatement) statement_.connection_
4478: .prepareStatement(insertString);
4479: } catch (SQLException sqle) {
4480: throw new SqlException(sqle);
4481: }
4482: }
4483:
4484: private void getPreparedStatementForUpdate() throws SqlException {
4485: // each column is associated with a tableName in the extended describe info.
4486: String updateString = buildUpdateString();
4487:
4488: if (updateString == null) {
4489: throw new SqlException(
4490: agent_.logWriter_,
4491: new ClientMessageId(
4492: SQLState.CURSOR_NO_UPDATE_CALLS_ON_CURRENT_ROW));
4493: }
4494: preparedStatementForUpdate_ = statement_.connection_
4495: .preparePositionedUpdateStatement(updateString,
4496: statement_.section_
4497: .getPositionedUpdateSection());
4498:
4499: }
4500:
4501: private void getPreparedStatementForDelete() throws SqlException {
4502: // each column is associated with a tableName in the extended describe info.
4503: String deleteString = buildDeleteString();
4504:
4505: preparedStatementForDelete_ = statement_.connection_
4506: .preparePositionedUpdateStatement(deleteString,
4507: statement_.section_
4508: .getPositionedUpdateSection()); // update section
4509: }
4510:
4511: private final void resetUpdatedColumnsForInsert() {
4512: // initialize updateColumns with nulls for all columns
4513: if (updatedColumns_ == null) {
4514: updatedColumns_ = new Object[resultSetMetaData_.columns_];
4515: }
4516: if (columnUpdated_ != null) {
4517: columnUpdated_ = new boolean[resultSetMetaData_.columns_];
4518: }
4519: for (int i = 0; i < updatedColumns_.length; i++) {
4520: updateColumn(i + 1, null);
4521: }
4522: for (int i = 0; i < columnUpdated_.length; i++) {
4523: columnUpdated_[i] = false;
4524: }
4525: }
4526:
4527: private final void resetUpdatedColumns() {
4528: if (updatedColumns_ != null) {
4529: for (int i = 0; i < updatedColumns_.length; i++) {
4530: updatedColumns_[i] = null;
4531: }
4532: }
4533: if (columnUpdated_ != null) {
4534: for (int i = 0; i < columnUpdated_.length; i++) {
4535: columnUpdated_[i] = false;
4536: }
4537: }
4538: }
4539:
4540: private final long getRowUncast() {
4541: return firstRowInRowset_ + currentRowInRowset_;
4542: }
4543:
4544: private final void checkGetterPreconditions(int column)
4545: throws SqlException {
4546: checkForClosedResultSet();
4547: checkForValidColumnIndex(column);
4548: checkForValidCursorPosition();
4549: }
4550:
4551: private final void checkUpdatePreconditions(int column,
4552: String operation) throws SqlException {
4553:
4554: checkForClosedResultSet();
4555: checkForValidColumnIndex(column);
4556: checkForUpdatableResultSet(operation);
4557:
4558: if (!isOnCurrentRow_ && !isOnInsertRow_) {
4559: throw new SqlException(
4560: agent_.logWriter_,
4561: new ClientMessageId(
4562: SQLState.CURSOR_NOT_ON_CURRENT_OR_INSERT_ROW));
4563: }
4564:
4565: if (resultSetMetaData_.sqlxUpdatable_ == null
4566: || resultSetMetaData_.sqlxUpdatable_[column - 1] != 1) {
4567: throw new SqlException(agent_.logWriter_,
4568: new ClientMessageId(
4569: SQLState.CURSOR_COLUMN_NOT_UPDATABLE));
4570: }
4571:
4572: //if not on a valid row, then do not accept updateXXX calls
4573: if (!isValidCursorPosition_)
4574: throw new SqlException(
4575: agent_.logWriter_,
4576: new ClientMessageId(
4577: SQLState.CURSOR_INVALID_OPERATION_AT_CURRENT_POSITION));
4578: }
4579:
4580: final void checkForValidColumnIndex(int column) throws SqlException {
4581: if (column < 1 || column > resultSetMetaData_.columns_) {
4582: throw new SqlException(agent_.logWriter_,
4583: new ClientMessageId(
4584: SQLState.LANG_INVALID_COLUMN_POSITION),
4585: new Integer(column), new Integer(
4586: resultSetMetaData_.columns_));
4587: }
4588: }
4589:
4590: protected final void checkForClosedResultSet() throws SqlException {
4591: if (!openOnClient_) {
4592: agent_.checkForDeferredExceptions();
4593: throw new SqlException(agent_.logWriter_,
4594: new ClientMessageId(
4595: SQLState.CLIENT_RESULT_SET_NOT_OPEN));
4596: } else {
4597: agent_.checkForDeferredExceptions();
4598: }
4599: }
4600:
4601: private final void checkForUpdatableResultSet(String operation)
4602: throws SqlException {
4603: if (resultSetConcurrency_ == java.sql.ResultSet.CONCUR_READ_ONLY) {
4604: throw new SqlException(
4605: agent_.logWriter_,
4606: new ClientMessageId(
4607: SQLState.UPDATABLE_RESULTSET_API_DISALLOWED),
4608: operation);
4609: }
4610: }
4611:
4612: private final void checkForValidCursorPosition()
4613: throws SqlException {
4614: if (!isValidCursorPosition_) {
4615: throw new SqlException(
4616: agent_.logWriter_,
4617: new ClientMessageId(
4618: SQLState.CURSOR_INVALID_OPERATION_AT_CURRENT_POSITION));
4619: }
4620: }
4621:
4622: private final void checkPositionedOnPlainRow() throws SqlException {
4623: if (isOnInsertRow_ || !isValidCursorPosition_) {
4624: throw new SqlException(agent_.logWriter_,
4625: new ClientMessageId(SQLState.NO_CURRENT_ROW));
4626: }
4627: }
4628:
4629: private final void checkThatResultSetTypeIsScrollable()
4630: throws SqlException {
4631: if (resultSetType_ == java.sql.ResultSet.TYPE_FORWARD_ONLY) {
4632: throw new SqlException(agent_.logWriter_,
4633: new ClientMessageId(
4634: SQLState.CURSOR_MUST_BE_SCROLLABLE));
4635: }
4636: }
4637:
4638: private final void checkThatResultSetIsNotDynamic()
4639: throws SqlException {
4640: if (sensitivity_ == sensitivity_sensitive_dynamic__) {
4641: throw new SqlException(
4642: agent_.logWriter_,
4643: new ClientMessageId(
4644: SQLState.CURSOR_INVALID_FOR_SENSITIVE_DYNAMIC));
4645: }
4646: }
4647:
4648: private boolean resultSetContainsNoRows() throws SqlException {
4649: if (rowCountIsUnknown()) {
4650: getRowCount();
4651: }
4652: return (rowCount_ == 0);
4653: }
4654:
4655: private boolean rowIsInCurrentRowset(long rowNumber, int orientation)
4656: throws SqlException {
4657: if (sensitivity_ == sensitivity_sensitive_dynamic__) {
4658: switch (orientation) {
4659: case scrollOrientation_next__:
4660: if (isAfterLast_) {
4661: return false;
4662: } else {
4663: return (currentRowInRowset_ + 1 < rowsReceivedInCurrentRowset_);
4664: }
4665: case scrollOrientation_prior__:
4666: if (isBeforeFirst_) {
4667: return false;
4668: } else {
4669: return (currentRowInRowset_ - 1 >= 0);
4670: }
4671: case scrollOrientation_relative__:
4672: return (rowNumber < rowsReceivedInCurrentRowset_ && rowNumber >= 0);
4673:
4674: // for dynamic cursors, we will not be able to check whether a row is in the cache for
4675: // FIRST, ABSOLUTE, AND LAST
4676: case scrollOrientation_first__:
4677: case scrollOrientation_absolute__:
4678: case scrollOrientation_last__:
4679: return false;
4680: default:
4681: return false;
4682: }
4683: } else {
4684: return rowIsInCurrentRowset(rowNumber);
4685: }
4686: }
4687:
4688: private boolean rowIsInCurrentRowset(long rowNumber)
4689: throws SqlException {
4690: // firstRowInRowset_ is equal to lastRowInRowset_ if there is only one row
4691: // in the rowset or if fetchSize_ is 1. however, return false if firstRowInRowset_
4692: // is equal to lastRowInRowset_ and also equal to zero which means there is no
4693: // valid row in the current rowset.
4694: if (firstRowInRowset_ == lastRowInRowset_
4695: && firstRowInRowset_ == 0) {
4696: return false;
4697: }
4698: if (rowNumber >= firstRowInRowset_
4699: && rowNumber <= lastRowInRowset_) {
4700: return true;
4701: } else {
4702: return false;
4703: }
4704: }
4705:
4706: private void markPositionedUpdateDeletePreparedStatementsClosed() {
4707: if (preparedStatementForUpdate_ != null) {
4708: preparedStatementForUpdate_.markClosed();
4709: preparedStatementForUpdate_ = null;
4710: }
4711: if (preparedStatementForDelete_ != null) {
4712: preparedStatementForDelete_.markClosed();
4713: preparedStatementForDelete_ = null;
4714: }
4715: }
4716:
4717: protected void updateColumnInfoFromCache() {
4718: // currentRowInRowset_ should never be bigger than the max value of an int,
4719: // because we have a driver imposed limit of fetch size 1000.
4720: cursor_.columnDataPosition_ = (int[]) cursor_.columnDataPositionCache_
4721: .get((int) currentRowInRowset_);
4722: cursor_.columnDataComputedLength_ = (int[]) cursor_.columnDataLengthCache_
4723: .get((int) currentRowInRowset_);
4724: cursor_.isNull_ = (boolean[]) cursor_.columnDataIsNullCache_
4725: .get((int) currentRowInRowset_);
4726: cursor_.isUpdateDeleteHole_ = ((Boolean) cursor_.isUpdateDeleteHoleCache_
4727: .get((int) currentRowInRowset_)).booleanValue();
4728: }
4729:
4730: protected final void checkAndThrowReceivedQueryTerminatingException()
4731: throws SqlException {
4732: // If we are in a split row, and before sending CNTQRY, check whether an ENDQRYRM
4733: // has been received.
4734: if (!openOnServer_) {
4735: SqlException sqlException = null;
4736: int sqlcode = org.apache.derby.client.am.Utils
4737: .getSqlcodeFromSqlca(queryTerminatingSqlca_);
4738: if (sqlcode < 0) {
4739: sqlException = new SqlException(agent_.logWriter_,
4740: queryTerminatingSqlca_);
4741: } else if (sqlcode > 0 && sqlcode != 100) {
4742: accumulateWarning(new SqlWarning(agent_.logWriter_,
4743: queryTerminatingSqlca_));
4744: }
4745: try {
4746: closeX(); // the auto commit logic is in closeX()
4747: } catch (SqlException e) {
4748: sqlException.setNextException(e);
4749: }
4750: if (sqlException != null) {
4751: throw sqlException;
4752: }
4753: }
4754: }
4755:
4756: public void parseScrollableRowset() throws SqlException {
4757: // modified check from qrydtaReturned to cursor.dataBufferHasUnprocesseData()
4758: if (cursor_.dataBufferHasUnprocessedData() && scrollable_) {
4759: parseRowset_();
4760: adjustFirstRowset();
4761:
4762: // This method is only called after open query to parse out the very first rowset
4763: // received.
4764: if (cursor_.allRowsReceivedFromServer()
4765: && rowsReceivedInCurrentRowset_ == 0) {
4766: setRowsetNoRowsEvent();
4767: }
4768: }
4769: }
4770:
4771: // determines if a cursor is a:
4772: // Return to Client - not to be read by the stored procedure only by client
4773: // Return to Caller - only calling JSP can read it, not the client
4774: public byte getRSReturnability() {
4775: return rsReturnability_;
4776: }
4777:
4778: public void setRSReturnability(byte rsReturnability) { // valid return type set it
4779: if ((rsReturnability == DDM_RETURN_CALLER)
4780: || (rsReturnability == DDM_RETURN_CLIENT)) {
4781: rsReturnability_ = rsReturnability;
4782: } else { // unknown return type, set DDM_RETURN_CALLER
4783: rsReturnability_ = DDM_RETURN_CALLER;
4784: }
4785: }
4786:
4787: //------------------------------------------------------------------------------
4788: // Push the getXXXRowset_() methods up from the material layers
4789: //------------------------------------------------------------------------------
4790: // This method is called to retrieve the total number of rows in the result set
4791: // and then reposition the cursor to where it was before.
4792: // The rowCount_ comes back in the SQLCA in fields SQLERRD1 and SQLERRD2 when
4793: // sqlcode is +100.
4794: protected void getRowCount() throws SqlException {
4795: // if already received an ENDQRYRM at open, check sqlcode and throw an exception
4796: checkAndThrowReceivedQueryTerminatingException();
4797:
4798: agent_.beginWriteChain(statement_);
4799:
4800: Section section = (generatedSection_ == null) ? statement_.section_
4801: : generatedSection_;
4802:
4803: // send the first CNTQRY to place cursor after last to retrieve the rowCount_.
4804: writePositioningFetch_(section, scrollOrientation_after__, 0);
4805: // if this is a non-dynamic rowset cursor, reposition the cursor to the first row in rowset
4806: // after the fetch after. Cache info and cursor positions on the client should not change.
4807: if (isRowsetCursor_
4808: && sensitivity_ != sensitivity_sensitive_dynamic__
4809: && firstRowInRowset_ != 0) {
4810: writePositioningFetch_(section,
4811: scrollOrientation_absolute__, firstRowInRowset_);
4812: }
4813:
4814: agent_.flow(statement_);
4815:
4816: readPositioningFetch_();
4817: if (isRowsetCursor_
4818: && sensitivity_ != sensitivity_sensitive_dynamic__
4819: && firstRowInRowset_ != 0) {
4820: readPositioningFetch_();
4821: }
4822:
4823: agent_.endReadChain();
4824:
4825: // if rowCount_ is not updated, check for exceptions
4826: if (rowCount_ == -1) {
4827: checkAndThrowReceivedQueryTerminatingException();
4828: }
4829:
4830: if (isRowsetCursor_
4831: && sensitivity_ != sensitivity_sensitive_dynamic__
4832: && firstRowInRowset_ != 0) {
4833: absolutePosition_ = firstRowInRowset_;
4834: } else {
4835: absolutePosition_ = (maxRows_ == 0) ? rowCount_ + 1
4836: : maxRows_ + 1;
4837: }
4838: }
4839:
4840: private void flowGetRowset(int orientation, long rowNumber)
4841: throws SqlException {
4842: // clear lobs before fetching rows
4843: cursor_.clearLobData_();
4844: cursor_.resetDataBuffer();
4845: agent_.beginWriteChain(statement_);
4846:
4847: writeScrollableFetch_(
4848: (generatedSection_ == null) ? statement_.section_
4849: : generatedSection_, fetchSize_, orientation,
4850: rowNumber, true); // true means to discard any pending partial
4851: // row and pending query blocks
4852:
4853: // reset the number of rows received to 0.
4854: // cannot use rowsRead_ here because this is reset every time a new rowset is fetched
4855: rowsReceivedInCurrentRowset_ = 0;
4856:
4857: agent_.flow(statement_);
4858: readScrollableFetch_();
4859: agent_.endReadChain();
4860: }
4861:
4862: private boolean getNextRowset() throws SqlException {
4863: // for rowset cursors or dynamic, non-rowset cursors
4864: if (isRowsetCursor_
4865: || sensitivity_ == sensitivity_sensitive_dynamic__) {
4866: // check if the next row contains a +100 before fetching from the server.
4867: // since index starts from 0, the actual row number for the current row is (currentRowInRowset_+1)
4868: // and the actual row number for the next row is (currentRowInRowset_+2)
4869: int sqlcode = checkRowsetSqlca((int) currentRowInRowset_ + 2);
4870: if (sqlcode == 100) {
4871: isAfterLast_ = true;
4872: return false;
4873: }
4874: flowGetRowset(scrollOrientation_next__, 0);
4875: } else {
4876: // for all other cursors:
4877: // sensitive static, insensitive, non-rowset cursors
4878: // if already afterLast, return false
4879: // if already on the last row and have received a +100, do not fetch again, return false
4880: if (resultSetContainsNoRows() || isAfterLastX()) {
4881: return false;
4882: } else if (firstRowInRowset_ + currentRowInRowset_ == lastRowInRowset_
4883: && cursor_.allRowsReceivedFromServer()) {
4884: isAfterLast_ = true;
4885: setRowsetAfterLastEvent();
4886: return false;
4887: }
4888:
4889: // rowNumber to fetch is 1 if absolute position is equal to the last row
4890: // in the rowset
4891: long rowNumber = 1;
4892: int orientation = scrollOrientation_relative__;
4893:
4894: // Normally absolute position is equal to last row in the rowset, but in cases
4895: // of previous "update where current of"s, absolute position may be somewhere
4896: // else in the current rowset, thus rowNumber needs to be recalculated based on
4897: // where in the rowset the absolute position is.
4898: if (absolutePosition_ < lastRowInRowset_) {
4899: rowNumber = lastRowInRowset_ - absolutePosition_ + 1;
4900: absolutePosition_ = lastRowInRowset_;
4901: }
4902: // the following case happens when a getRowCount() is called and we flow a fetch after
4903: // to get the rowCount.
4904: else if (absolutePosition_ > lastRowInRowset_) {
4905: rowNumber = lastRowInRowset_ + 1;
4906: orientation = scrollOrientation_absolute__;
4907: }
4908:
4909: flowGetRowset(orientation, rowNumber);
4910: }
4911:
4912: parseRowset_();
4913:
4914: // If no row was received but received sqlcode +100, then the cursor is
4915: // positioned after last.
4916: if (rowsReceivedInCurrentRowset_ == 0
4917: && cursor_.allRowsReceivedFromServer()) {
4918: isAfterLast_ = true;
4919: setRowsetAfterLastEvent();
4920: return false;
4921: }
4922:
4923: // adjust the cursor positions for sensitive static or insensitive cursors only
4924: if (sensitivity_ != sensitivity_sensitive_dynamic__) {
4925: adjustNextRowset();
4926: }
4927: currentRowInRowset_ = 0;
4928: return true;
4929: }
4930:
4931: private void adjustNextRowset() {
4932: firstRowInRowset_ = lastRowInRowset_ + 1;
4933: lastRowInRowset_ = lastRowInRowset_
4934: + rowsReceivedInCurrentRowset_;
4935: setAbsolutePositionBasedOnAllRowsReceived();
4936: //currentRowInRowset_ = 0;
4937: }
4938:
4939: private boolean getPreviousRowset() throws SqlException {
4940: int orientation = scrollOrientation_relative__;
4941: long rowNumber = 0;
4942: boolean isAfterLast = false;
4943:
4944: // for rowset cursors or dynamic, non-rowset cursors
4945: if (isRowsetCursor_
4946: || sensitivity_ == sensitivity_sensitive_dynamic__) {
4947: // check if we already received a +20237 before fetching from the server.
4948: if (currentRowInRowset_ == 0 && rowsetSqlca_ != null
4949: && rowsetSqlca_[0] != null
4950: && rowsetSqlca_[0].getSqlCode() == 20237) {
4951: isBeforeFirst_ = true;
4952: setRowsetBeforeFirstEvent();
4953: return false;
4954: }
4955: flowGetRowset(scrollOrientation_prior__, 0);
4956: } else {
4957: // for all other cursors:
4958: // sensitive static, insensitive, non-rowset cursors
4959: if (resultSetContainsNoRows() || isBeforeFirstX()) {
4960: return false;
4961: }
4962: rowNumber = firstRowInRowset_ - absolutePosition_
4963: - fetchSize_;
4964: isAfterLast = isAfterLastX();
4965: if (isFirstX()) {
4966: rowNumber = 0;
4967: orientation = scrollOrientation_absolute__;
4968: }
4969: // If the cursor is after last, fetch the last rowset which includes the last row.
4970: else if (isAfterLast) {
4971: rowNumber = (-1) * fetchSize_;
4972: }
4973: // if the distance from the absolute position is less than fetch size, fetch from row 1
4974: if (rowNumber * (-1) >= absolutePosition_) {
4975: rowNumber = 1;
4976: orientation = scrollOrientation_absolute__;
4977: }
4978:
4979: // If afterLast and maxRows > 0, go backward from maxRows and not
4980: // from last row in the resultSet
4981: if (maxRows_ > 0
4982: && orientation == scrollOrientation_relative__
4983: && isAfterLast) {
4984: rowNumber += maxRows_ + 1;
4985: orientation = scrollOrientation_absolute__;
4986: }
4987:
4988: flowGetRowset(orientation, rowNumber);
4989: }
4990:
4991: parseRowset_();
4992:
4993: // If no row was received but received sqlcode +100, then the cursor is
4994: // positioned before first.
4995: if (rowsReceivedInCurrentRowset_ == 0
4996: && cursor_.allRowsReceivedFromServer()) {
4997: isBeforeFirst_ = true;
4998: setRowsetBeforeFirstEvent();
4999: return false;
5000: }
5001:
5002: // adjust the cursor positions for sensitive static or insensitive cursors only
5003: if (sensitivity_ != sensitivity_sensitive_dynamic__) {
5004: adjustPreviousRowset(orientation, rowNumber, isAfterLast);
5005: } else {
5006: currentRowInRowset_ = rowsReceivedInCurrentRowset_ - 1;
5007: }
5008: return true;
5009: }
5010:
5011: private void adjustPreviousRowset(int orientation, long rowNumber,
5012: boolean isAfterLastRow) throws SqlException {
5013: if (orientation == scrollOrientation_absolute__
5014: && rowNumber == 1) {
5015: // Subtracting 2 because the currentRowInRowset_ index starts at 0, and all
5016: // the other indexes starts at 1.
5017: currentRowInRowset_ = (isAfterLastRow) ? absolutePosition_ - 2
5018: : firstRowInRowset_ - 2;
5019: firstRowInRowset_ = 1;
5020: lastRowInRowset_ = rowsReceivedInCurrentRowset_;
5021: absolutePosition_ = (isAfterLastRow) ? lastRowInRowset_ + 1
5022: : lastRowInRowset_;
5023: } else {
5024: if (maxRows_ == 0)
5025: lastRowInRowset_ = (isAfterLastRow) ? rowCount_
5026: : firstRowInRowset_ - 1;
5027: else
5028: lastRowInRowset_ = (isAfterLastRow) ? maxRows_
5029: : firstRowInRowset_ - 1;
5030: firstRowInRowset_ = lastRowInRowset_
5031: - rowsReceivedInCurrentRowset_ + 1;
5032: absolutePosition_ = lastRowInRowset_;
5033: currentRowInRowset_ = lastRowInRowset_ - firstRowInRowset_;
5034: }
5035: }
5036:
5037: private boolean getAbsoluteRowset(long row) throws SqlException {
5038: int orientation = scrollOrientation_absolute__;
5039: // absolute(0) is not allowed on a rowset cursor, will get -644 from the server
5040: // remap to fetch before.
5041: if (isRowsetCursor_ && row == 0) {
5042: orientation = scrollOrientation_before__;
5043: } else if (sensitivity_ != sensitivity_sensitive_dynamic__
5044: && row < 0) {
5045: row = 0;
5046: }
5047:
5048: flowGetRowset(orientation, row);
5049: parseRowset_();
5050:
5051: // If no row was received but received sqlcode +100, then the cursor is
5052: // positioned after last or before first.
5053: if ((rowsReceivedInCurrentRowset_ == 0 && cursor_
5054: .allRowsReceivedFromServer())
5055: || orientation == scrollOrientation_before__) {
5056: if (row > 0) {
5057: setRowsetAfterLastEvent();
5058: isAfterLast_ = true;
5059: } else {
5060: setRowsetBeforeFirstEvent();
5061: isBeforeFirst_ = true;
5062: }
5063: return false;
5064: }
5065:
5066: // adjust the cursor positions for sensitive static or insensitive cursors only
5067: if (sensitivity_ != sensitivity_sensitive_dynamic__) {
5068: adjustAbsoluteRowset(row);
5069: }
5070: currentRowInRowset_ = 0;
5071: return true;
5072: }
5073:
5074: private void adjustAbsoluteRowset(long rowNumber) {
5075: firstRowInRowset_ = rowNumber;
5076: lastRowInRowset_ = firstRowInRowset_
5077: + rowsReceivedInCurrentRowset_ - 1;
5078: setAbsolutePositionBasedOnAllRowsReceived();
5079: //currentRowInRowset_ = 0;
5080: }
5081:
5082: private boolean getRelativeRowset(long rows) throws SqlException {
5083: if (rows == 0
5084: && (cursor_.allRowsReceivedFromServer() || absolutePosition_ > rowCount_)) {
5085: setRowsetAfterLastEvent();
5086: isAfterLast_ = true;
5087: return false;
5088: }
5089:
5090: flowGetRowset(scrollOrientation_relative__, rows);
5091: parseRowset_();
5092:
5093: if (rowsReceivedInCurrentRowset_ == 0
5094: && cursor_.allRowsReceivedFromServer()) {
5095: if (rows > 0) {
5096: setRowsetAfterLastEvent();
5097: isAfterLast_ = true;
5098: } else {
5099: setRowsetBeforeFirstEvent();
5100: isBeforeFirst_ = true;
5101: }
5102: return false;
5103: }
5104:
5105: // adjust the cursor positions for sensitive static or insensitive cursors only
5106: if (sensitivity_ != sensitivity_sensitive_dynamic__) {
5107: adjustRelativeRowset(rows);
5108: }
5109: currentRowInRowset_ = 0;
5110: return true;
5111: }
5112:
5113: private void adjustRelativeRowset(long rowNumber) {
5114: firstRowInRowset_ = absolutePosition_ + rowNumber;
5115: lastRowInRowset_ = firstRowInRowset_
5116: + rowsReceivedInCurrentRowset_ - 1;
5117: setAbsolutePositionBasedOnAllRowsReceived();
5118: }
5119:
5120: private boolean getFirstRowset() throws SqlException {
5121: flowGetRowset(scrollOrientation_absolute__, 1);
5122: parseRowset_();
5123:
5124: // If no row was received but received sqlcode +100, then no row in the result set
5125: if (rowsReceivedInCurrentRowset_ == 0
5126: && cursor_.allRowsReceivedFromServer()) {
5127: resetRowsetFlags();
5128: this .setRowsetNoRowsEvent();
5129: return false;
5130: }
5131:
5132: // adjust the cursor positions for sensitive static or insensitive cursors only
5133: if (sensitivity_ != sensitivity_sensitive_dynamic__) {
5134: adjustFirstRowset();
5135: }
5136: currentRowInRowset_ = 0;
5137: return true;
5138: }
5139:
5140: private void adjustFirstRowset() {
5141: firstRowInRowset_ = 1;
5142: lastRowInRowset_ = rowsReceivedInCurrentRowset_;
5143: setAbsolutePositionBasedOnAllRowsReceived();
5144: //currentRowInRowset_ = 0;
5145: }
5146:
5147: private boolean getLastRowset(long row) throws SqlException {
5148: if (sensitivity_ != sensitivity_sensitive_dynamic__
5149: && rowCount_ == 0) {
5150: isAfterLast_ = false;
5151: isBeforeFirst_ = false;
5152: setRowsetNoRowsEvent();
5153: return false;
5154: } else if (isRowsetCursor_
5155: || sensitivity_ == sensitivity_sensitive_dynamic__) {
5156: flowGetRowset(scrollOrientation_last__, 0);
5157: } else {
5158: // If fetchSize_ is smaller than the total number of rows in the ResultSet,
5159: // then fetch one rowset of fetchSize_ number of rows. Otherwise, we will
5160: // fetch all rows in the ResultSet, so start fetching from row 1.
5161: long rowNumber;
5162: if (maxRows_ == 0) {
5163: rowNumber = (fetchSize_ < row) ? ((-1) * fetchSize_)
5164: : 1;
5165: } else {
5166: rowNumber = (fetchSize_ < row) ? (maxRows_ - fetchSize_) + 1
5167: : 1;
5168: }
5169: flowGetRowset(scrollOrientation_absolute__, rowNumber);
5170: }
5171: parseRowset_();
5172:
5173: if (rowsReceivedInCurrentRowset_ == 0
5174: && cursor_.allRowsReceivedFromServer()) {
5175: isAfterLast_ = true;
5176: setRowsetAfterLastEvent();
5177: return false;
5178: }
5179:
5180: // adjust the cursor positions for sensitive static or insensitive cursors only
5181: if (sensitivity_ != sensitivity_sensitive_dynamic__) {
5182: adjustLastRowset(row);
5183: } else {
5184: currentRowInRowset_ = rowsReceivedInCurrentRowset_ - 1;
5185: }
5186: return true;
5187: }
5188:
5189: private void adjustLastRowset(long row) {
5190: lastRowInRowset_ = row;
5191: firstRowInRowset_ = lastRowInRowset_
5192: - rowsReceivedInCurrentRowset_ + 1;
5193: if (firstRowInRowset_ <= 0) {
5194: firstRowInRowset_ = 1;
5195: }
5196: setAbsolutePositionBasedOnAllRowsReceived();
5197: currentRowInRowset_ = lastRowInRowset_ - firstRowInRowset_;
5198: }
5199:
5200: private boolean getRefreshRowset() throws SqlException {
5201: if (isRowsetCursor_) {
5202: flowGetRowset(scrollOrientation_current__, 0);
5203: } else {
5204: flowGetRowset(scrollOrientation_relative__, (-1)
5205: * (absolutePosition_ - firstRowInRowset_));
5206: }
5207:
5208: parseRowset_();
5209:
5210: // Rowset indexes do not change when rowset is refreshed.
5211: // The only exception is absolutePosition_. It may be different after the refresh.
5212: if (sensitivity_ != sensitivity_sensitive_dynamic__) {
5213: adjustRefreshRowset();
5214: }
5215: return true;
5216: }
5217:
5218: private void adjustRefreshRowset() {
5219: setAbsolutePositionBasedOnAllRowsReceived();
5220: updateColumnInfoFromCache();
5221: }
5222:
5223: private void setAbsolutePositionBasedOnAllRowsReceived() {
5224: absolutePosition_ = (cursor_.allRowsReceivedFromServer()) ? lastRowInRowset_ + 1
5225: : lastRowInRowset_;
5226: }
5227:
5228: // ------------------------------- abstract box car methods --------------------------------------
5229: public abstract void writeFetch_(Section section)
5230: throws SqlException;
5231:
5232: public abstract void readFetch_() throws SqlException;
5233:
5234: public abstract void writeScrollableFetch_(Section section,
5235: int fetchSize, // need to send fetchSize in case when we get an
5236: // incomplete rowset, the fetchSize is the remaining
5237: // number of the rows in the rowset.
5238: int orientation, long rowToFetch, boolean resetQueryBlocks)
5239: throws SqlException;
5240:
5241: public abstract void readScrollableFetch_() throws SqlException;
5242:
5243: public abstract void writePositioningFetch_(Section section,
5244: int orientation, long rowToFetch) throws SqlException;
5245:
5246: public abstract void readPositioningFetch_() throws SqlException;
5247:
5248: public abstract void writeCursorClose_(Section section)
5249: throws SqlException;
5250:
5251: public abstract void readCursorClose_() throws SqlException;
5252:
5253: protected abstract void parseRowset_() throws SqlException;
5254:
5255: public abstract void setFetchSize_(int rows);
5256:
5257: /**
5258: * Method that is invoked by <code>closeX()</code> before the
5259: * result set is actually being closed. Subclasses may override
5260: * this method if work needs to be done before closing.
5261: *
5262: * @exception SqlException
5263: */
5264: protected abstract void preClose_() throws SqlException;
5265:
5266: public ConnectionCallbackInterface getConnectionCallbackInterface() {
5267: return connection_;
5268: }
5269:
5270: public StatementCallbackInterface getStatementCallbackInterface() {
5271: return statement_;
5272: }
5273:
5274: public void expandRowsetSqlca() {
5275: // rowsetSqlca_ index starts from 1. entry 0 is reserved for warning +20237
5276: // if rowset size is n, then the (n+1)th entry is reserved for the +100 if one is received.
5277: // thus the size of the rowsetSqlca_ needs to be fetchSize_+2
5278: if (isRowsetCursor_
5279: && (rowsetSqlca_ == null || rowsetSqlca_.length < fetchSize_ + 2)) {
5280: rowsetSqlca_ = new Sqlca[fetchSize_ + 2];
5281: }
5282: }
5283:
5284: private final int checkRowsetSqlca() throws SqlException {
5285: return checkRowsetSqlca((int) currentRowInRowset_ + 1);
5286: }
5287:
5288: private final int checkRowsetSqlca(int row) throws SqlException {
5289: int sqlcode = 0;
5290: if (!isRowsetCursor_ || rowsetSqlca_ == null
5291: || rowsetSqlca_[row] == null) {
5292: warnings_ = null; // clear any previous warnings
5293: return sqlcode;
5294: }
5295:
5296: Sqlca sqlca = rowsetSqlca_[row];
5297: if (sqlca != null) {
5298: sqlcode = sqlca.getSqlCode();
5299: if (sqlcode < 0) {
5300: throw new SqlException(agent_.logWriter_, sqlca);
5301: } else if (sqlcode > 0
5302: && (sqlcode != 100 && sqlcode != +20237)) {
5303: accumulateWarning(new SqlWarning(agent_.logWriter_,
5304: sqlca));
5305: }
5306: }
5307: return sqlcode;
5308: }
5309:
5310: private void resetRowsetFlags() {
5311: isBeforeFirst_ = false;
5312: isAfterLast_ = false;
5313: isFirst_ = false;
5314: isLast_ = false;
5315: }
5316:
5317: private void resetRowsetSqlca() {
5318: if (rowsetSqlca_ != null) {
5319: for (int i = 0; i < rowsetSqlca_.length; i++) {
5320: rowsetSqlca_[i] = null;
5321: }
5322: }
5323: }
5324:
5325: private CloseFilterInputStream createCloseFilterInputStream(
5326: java.io.InputStream is) throws SqlException {
5327:
5328: if (is == null) {
5329: return null;
5330: }
5331:
5332: if (is_ == is) {
5333: return is_;
5334: }
5335:
5336: closeCloseFilterInputStream();
5337:
5338: is_ = new CloseFilterInputStream(is);
5339:
5340: return is_;
5341:
5342: }
5343:
5344: private void closeCloseFilterInputStream() throws SqlException {
5345:
5346: if (is_ != null) {
5347: try {
5348: is_.close();
5349:
5350: } catch (IOException e) {
5351: throw new SqlException(agent_.logWriter_,
5352: new ClientMessageId(SQLState.JAVA_EXCEPTION),
5353: "java.io.IOException", e.getMessage(), e);
5354: }
5355:
5356: is_ = null;
5357:
5358: }
5359: }
5360:
5361: void useStream(int columnIndex) throws SqlException {
5362:
5363: if (streamUsedFlags_[columnIndex - 1]) {
5364: throw new SqlException(agent_.logWriter_,
5365: new ClientMessageId(
5366: SQLState.LANG_STREAM_RETRIEVED_ALREADY));
5367: }
5368:
5369: streamUsedFlags_[columnIndex - 1] = true;
5370:
5371: }
5372:
5373: private void unuseStreams() {
5374:
5375: if (streamUsedFlags_ == null) {
5376: streamUsedFlags_ = new boolean[resultSetMetaData_.columns_];
5377: return;
5378: }
5379:
5380: for (int i = 0; i < streamUsedFlags_.length; i++) {
5381:
5382: streamUsedFlags_[i] = false;
5383:
5384: }
5385:
5386: }
5387:
5388: private SQLException jdbc3MethodNotSupported() {
5389: return new SqlException(agent_.logWriter_, new ClientMessageId(
5390: SQLState.JDBC_METHOD_NOT_IMPLEMENTED))
5391: .getSQLException();
5392: }
5393:
5394: // -------------------------- JDBC 4.0 --------------------------
5395:
5396: /**
5397: * Retrieves the holdability for this <code>ResultSet</code>
5398: * object.
5399: *
5400: * @return either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
5401: * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
5402: * @exception SQLException if a database error occurs
5403: */
5404: public final int getHoldability() throws SQLException {
5405: if (agent_.loggingEnabled()) {
5406: agent_.logWriter_.traceEntry(this , "getHoldability");
5407: }
5408: try {
5409: checkForClosedResultSet();
5410: } catch (SqlException se) {
5411: throw se.getSQLException();
5412: }
5413: if (agent_.loggingEnabled()) {
5414: agent_.logWriter_.traceExit(this , "getHoldability",
5415: resultSetHoldability_);
5416: }
5417: return resultSetHoldability_;
5418: }
5419:
5420: /**
5421: * Checks whether this <code>ResultSet</code> object has been
5422: * closed, either automatically or because <code>close()</code>
5423: * has been called.
5424: *
5425: * @return <code>true</code> if the <code>ResultSet</code> is
5426: * closed, <code>false</code> otherwise
5427: * @exception SQLException if a database error occurs
5428: */
5429: public final boolean isClosed() throws SQLException {
5430: if (agent_.loggingEnabled()) {
5431: agent_.logWriter_.traceEntry(this , "isClosed");
5432: }
5433: final boolean isClosed = !openOnClient_;
5434: if (agent_.loggingEnabled()) {
5435: agent_.logWriter_.traceExit(this , "isClosed", isClosed);
5436: }
5437: return isClosed;
5438: }
5439:
5440: /**
5441: * Updates the designated column with an ascii stream value.
5442: * The data will be read from the stream as needed until end-of-stream is
5443: * reached.
5444: *
5445: * The updater methods are used to update column values in the current row
5446: * or the insert row. The updater methods do not update the underlying
5447: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5448: * methods are called to update the database.
5449: *
5450: * @param columnIndex the first column is 1, the second is 2, ...
5451: * @param x the new column value
5452: * @throws SQLException if the columnIndex is not valid; if a database
5453: * access error occurs; the result set concurrency is
5454: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5455: * result set
5456: */
5457: public void updateAsciiStream(int columnIndex, InputStream x)
5458: throws SQLException {
5459: synchronized (connection_) {
5460: if (agent_.loggingEnabled()) {
5461: agent_.logWriter_.traceEntry(this , "updateAsciiStream",
5462: columnIndex, x);
5463: }
5464: try {
5465: checkUpdatePreconditions(columnIndex,
5466: "updateAsciiStream");
5467: updateColumn(
5468: columnIndex,
5469: agent_.crossConverters_
5470: .setObjectFromCharacterStream(
5471: resultSetMetaData_.types_[columnIndex - 1],
5472: x, "US-ASCII",
5473: CrossConverters.UNKNOWN_LENGTH));
5474: } catch (SqlException se) {
5475: throw se.getSQLException();
5476: }
5477: }
5478: }
5479:
5480: /**
5481: * Update a column with an ascii stream value.
5482: *
5483: * The updateXXX() methods are used to update column values in the current
5484: * row, or the insert row. The updateXXX() methods do not update the
5485: * underlying database, instead the updateRow() or insertRow() methods are
5486: * called to update the database.
5487: *
5488: * @param columnIndex
5489: * the first column is 1, the second is 2, ...
5490: * @param x
5491: * the new column value
5492: * @param length
5493: * the length of the stream
5494: * @exception SQLException
5495: * if a database-access error occurs
5496: */
5497: public void updateAsciiStream(int columnIndex, InputStream x,
5498: long length) throws SQLException {
5499: if (length > Integer.MAX_VALUE)
5500: throw new SqlException(
5501: agent_.logWriter_,
5502: new ClientMessageId(
5503: SQLState.CLIENT_LENGTH_OUTSIDE_RANGE_FOR_DATATYPE),
5504: new Long(length), new Integer(Integer.MAX_VALUE))
5505: .getSQLException();
5506: else
5507: updateAsciiStream(columnIndex, x, (int) length);
5508: }
5509:
5510: /**
5511: * Updates the designated column with a binary stream value.
5512: * The data will be read from the stream as needed until end-of-stream is
5513: * reached.
5514: *
5515: * The updater methods are used to update column values in the current row
5516: * or the insert row. The updater methods do not update the underlying
5517: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5518: * methods are called to update the database.
5519: *
5520: * @param columnIndex the first column is 1, the second is 2, ...
5521: * @param x the new column value
5522: * @throws SQLException if the columnIndex is not valid; if a database
5523: * access error occurs; the result set concurrency is
5524: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5525: * result set
5526: */
5527: public void updateBinaryStream(int columnIndex, InputStream x)
5528: throws SQLException {
5529: synchronized (connection_) {
5530: if (agent_.loggingEnabled()) {
5531: agent_.logWriter_.traceEntry(this ,
5532: "updateBinaryStream", columnIndex, x);
5533: }
5534: try {
5535: checkUpdatePreconditions(columnIndex,
5536: "updateBinaryStream");
5537: updateColumn(
5538: columnIndex,
5539: agent_.crossConverters_
5540: .setObjectFromBinaryStream(
5541: resultSetMetaData_.types_[columnIndex - 1],
5542: x,
5543: CrossConverters.UNKNOWN_LENGTH));
5544: } catch (SqlException se) {
5545: throw se.getSQLException();
5546: }
5547: }
5548: }
5549:
5550: /**
5551: * Update a column with a binary stream value.
5552: *
5553: * The updateXXX() methods are used to update column values in the current
5554: * row, or the insert row. The updateXXX() methods do not update the
5555: * underlying database, instead the updateRow() or insertRow() methods are
5556: * called to update the database.
5557: *
5558: * @param columnIndex
5559: * the first column is 1, the second is 2, ...
5560: * @param x
5561: * the new column value
5562: * @param length
5563: * the length of the stream
5564: * @exception SQLException
5565: * if a database-access error occurs
5566: */
5567: public void updateBinaryStream(int columnIndex, InputStream x,
5568: long length) throws SQLException {
5569: if (length > Integer.MAX_VALUE)
5570: throw new SqlException(
5571: agent_.logWriter_,
5572: new ClientMessageId(
5573: SQLState.CLIENT_LENGTH_OUTSIDE_RANGE_FOR_DATATYPE),
5574: new Long(length), new Integer(Integer.MAX_VALUE))
5575: .getSQLException();
5576: else
5577: updateBinaryStream(columnIndex, x, (int) length);
5578:
5579: }
5580:
5581: /**
5582: * Updates the designated column using the given input stream.
5583: * The data will be read from the stream as needed until end-of-stream is
5584: * reached.
5585: *
5586: * The updater methods are used to update column values in the current row
5587: * or the insert row. The updater methods do not update the underlying
5588: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5589: * methods are called to update the database.
5590: *
5591: * @param columnIndex the first column is 1, the second is 2, ...
5592: * @param x the new column value
5593: * @throws SQLException if the columnIndex is not valid; if a database
5594: * access error occurs; the result set concurrency is
5595: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5596: * result set
5597: */
5598: public void updateBlob(int columnIndex, InputStream x)
5599: throws SQLException {
5600: synchronized (connection_) {
5601: if (agent_.loggingEnabled()) {
5602: agent_.logWriter_.traceEntry(this , "updateBlob",
5603: columnIndex, x);
5604: }
5605: try {
5606: checkUpdatePreconditions(columnIndex, "updateBlob");
5607: updateColumn(
5608: columnIndex,
5609: agent_.crossConverters_
5610: .setObject(
5611: resultSetMetaData_.types_[columnIndex - 1],
5612: new Blob(agent_, x)));
5613: } catch (SqlException se) {
5614: throw se.getSQLException();
5615: }
5616: }
5617: }
5618:
5619: /**
5620: * Updates the designated column with a character stream value.
5621: * The data will be read from the stream as needed until end-of-stream is
5622: * reached.
5623: *
5624: * The updater methods are used to update column values in the current row
5625: * or the insert row. The updater methods do not update the underlying
5626: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5627: * methods are called to update the database.
5628: *
5629: * @param columnIndex the first column is 1, the second is 2, ...
5630: * @param reader the new column value
5631: * @throws SQLException if the columnLabel is not valid; if a database
5632: * access error occurs; the result set concurrency is
5633: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5634: * result set
5635: */
5636: public void updateCharacterStream(int columnIndex, Reader reader)
5637: throws SQLException {
5638: synchronized (connection_) {
5639: try {
5640: if (agent_.loggingEnabled()) {
5641: agent_.logWriter_.traceEntry(this ,
5642: "updateCharacterStream", columnIndex,
5643: reader);
5644: }
5645: checkUpdatePreconditions(columnIndex,
5646: "updateCharacterStream");
5647: updateColumn(
5648: columnIndex,
5649: agent_.crossConverters_
5650: .setObject(
5651: resultSetMetaData_.types_[columnIndex - 1],
5652: reader,
5653: CrossConverters.UNKNOWN_LENGTH));
5654: } catch (SqlException se) {
5655: throw se.getSQLException();
5656: }
5657: }
5658: }
5659:
5660: /**
5661: * Update a column with a character stream value.
5662: *
5663: * The updateXXX() methods are used to update column values in the current
5664: * row, or the insert row. The updateXXX() methods do not update the
5665: * underlying database, instead the updateRow() or insertRow() methods are
5666: * called to update the database.
5667: *
5668: * @param columnIndex
5669: * the first column is 1, the second is 2, ...
5670: * @param x
5671: * the new column value
5672: * @param length
5673: * the length of the stream
5674: * @exception SQLException
5675: * if a database-access error occurs
5676: */
5677: public void updateCharacterStream(int columnIndex, Reader x,
5678: long length) throws SQLException {
5679: if (length > Integer.MAX_VALUE)
5680: throw new SqlException(
5681: agent_.logWriter_,
5682: new ClientMessageId(
5683: SQLState.CLIENT_LENGTH_OUTSIDE_RANGE_FOR_DATATYPE),
5684: new Long(length), new Integer(Integer.MAX_VALUE))
5685: .getSQLException();
5686: else
5687: updateCharacterStream(columnIndex, x, (int) length);
5688: }
5689:
5690: /**
5691: * Updates the designated column using the given <code>Reader</code>
5692: * object.
5693: * The data will be read from the stream as needed until end-of-stream is
5694: * reached. The JDBC driver will do any necessary conversion from UNICODE
5695: * to the database char format.
5696: *
5697: * The updater methods are used to update column values in the current row
5698: * or the insert row. The updater methods do not update the underlying
5699: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5700: * methods are called to update the database.
5701: *
5702: * @param columnIndex the first column is 1, the second is 2, ...
5703: * @param reader an object that contains the data to set the parameter
5704: * value to.
5705: * @throws SQLException if the columnIndex is not valid; if a database
5706: * access error occurs; the result set concurrency is
5707: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5708: * result set
5709: */
5710: public void updateClob(int columnIndex, Reader reader)
5711: throws SQLException {
5712: synchronized (connection_) {
5713: if (agent_.loggingEnabled()) {
5714: agent_.logWriter_.traceEntry(this , "updateClob",
5715: columnIndex, reader);
5716: }
5717: try {
5718: checkUpdatePreconditions(columnIndex, "updateClob");
5719: updateColumn(
5720: columnIndex,
5721: agent_.crossConverters_
5722: .setObject(
5723: resultSetMetaData_.types_[columnIndex - 1],
5724: new Clob(agent_, reader)));
5725: } catch (SqlException se) {
5726: throw se.getSQLException();
5727: }
5728: }
5729: }
5730:
5731: /**
5732: * Updates the designated column with an ascii stream value.
5733: * The data will be read from the stream as needed until end-of-stream is
5734: * reached.
5735: *
5736: * The updater methods are used to update column values in the current row
5737: * or the insert row. The updater methods do not update the underlying
5738: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5739: * methods are called to update the database.
5740: *
5741: * @param columnName the label for the column specified with the SQL AS
5742: * clause. If the SQL AS clause was not specified, then the label is
5743: * the name of the column
5744: * @param x the new column value
5745: * @throws SQLException if the columnLabel is not valid; if a database
5746: * access error occurs; the result set concurrency is
5747: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5748: * result set
5749: */
5750: public void updateAsciiStream(String columnName, InputStream x)
5751: throws SQLException {
5752: try {
5753: updateAsciiStream(findColumnX(columnName), x);
5754: } catch (SqlException se) {
5755: throw se.getSQLException();
5756: }
5757: }
5758:
5759: /**
5760: * Update a column with an ascii stream value.
5761: *
5762: * The updateXXX() methods are used to update column values in the current
5763: * row, or the insert row. The updateXXX() methods do not update the
5764: * underlying database, instead the updateRow() or insertRow() methods are
5765: * called to update the database.
5766: *
5767: * @param columnName
5768: * the name of the column
5769: * @param x
5770: * the new column value
5771: * @param length
5772: * of the stream
5773: * @exception SQLException
5774: * if a database-access error occurs
5775: */
5776: public void updateAsciiStream(String columnName, InputStream x,
5777: long length) throws SQLException {
5778: try {
5779: updateAsciiStream(findColumnX(columnName), x, length);
5780: } catch (SqlException sqle) {
5781: throw sqle.getSQLException();
5782: }
5783: }
5784:
5785: /**
5786: * Updates the designated column with a binary stream value.
5787: * The data will be read from the stream as needed until end-of-stream is
5788: * reached.
5789: *
5790: * The updater methods are used to update column values in the current row
5791: * or the insert row. The updater methods do not update the underlying
5792: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5793: * methods are called to update the database.
5794: *
5795: * @param columnLabel the label for the column specified with the SQL AS
5796: * clause. If the SQL AS clause was not specified, then the label is
5797: * the name of the column
5798: * @param x the new column value
5799: * @throws SQLException if the columnLabel is not valid; if a database
5800: * access error occurs; the result set concurrency is
5801: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5802: * result set
5803: */
5804: public void updateBinaryStream(String columnLabel, InputStream x)
5805: throws SQLException {
5806: try {
5807: updateBinaryStream(findColumnX(columnLabel), x);
5808: } catch (SqlException se) {
5809: throw se.getSQLException();
5810: }
5811: }
5812:
5813: /**
5814: * Update a column with a binary stream value.
5815: *
5816: * The updateXXX() methods are used to update column values in the current
5817: * row, or the insert row. The updateXXX() methods do not update the
5818: * underlying database, instead the updateRow() or insertRow() methods are
5819: * called to update the database.
5820: *
5821: * @param columnName
5822: * the name of the column
5823: * @param x
5824: * the new column value
5825: * @param length
5826: * of the stream
5827: * @exception SQLException
5828: * if a database-access error occurs
5829: */
5830: public void updateBinaryStream(String columnName, InputStream x,
5831: long length) throws SQLException {
5832: try {
5833: updateBinaryStream(findColumnX(columnName), x, length);
5834: } catch (SqlException sqle) {
5835: throw sqle.getSQLException();
5836: }
5837: }
5838:
5839: /**
5840: * Updates the designated column using the given input stream.
5841: * The data will be read from the stream as needed until end-of-stream is
5842: * reached.
5843: *
5844: * The updater methods are used to update column values in the current row
5845: * or the insert row. The updater methods do not update the underlying
5846: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5847: * methods are called to update the database.
5848: *
5849: * @param columnLabel the label for the column specified with the SQL AS
5850: * clause. If the SQL AS clause was not specified, then the label is
5851: * the name of the column
5852: * @param x the new column value
5853: * @throws SQLException if the columnLabel is not valid; if a database
5854: * access error occurs; the result set concurrency is
5855: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5856: * result set
5857: */
5858: public void updateBlob(String columnLabel, InputStream x)
5859: throws SQLException {
5860: try {
5861: updateBlob(findColumnX(columnLabel), x);
5862: } catch (SqlException se) {
5863: throw se.getSQLException();
5864: }
5865: }
5866:
5867: /**
5868: * Updates the designated column with a character stream value.
5869: * The data will be read from the stream as needed until end-of-stream is
5870: * reached.
5871: *
5872: * The updater methods are used to update column values in the current row
5873: * or the insert row. The updater methods do not update the underlying
5874: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5875: * methods are called to update the database.
5876: *
5877: * @param columnLabel the label for the column specified with the SQL AS
5878: * clause. If the SQL AS clause was not specified, then the label is
5879: * the name of the column
5880: * @param reader the new column value
5881: * @throws SQLException if the columnLabel is not valid; if a database
5882: * access error occurs; the result set concurrency is
5883: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5884: * result set
5885: */
5886: public void updateCharacterStream(String columnLabel, Reader reader)
5887: throws SQLException {
5888: try {
5889: updateCharacterStream(findColumnX(columnLabel), reader);
5890: } catch (SqlException se) {
5891: throw se.getSQLException();
5892: }
5893: }
5894:
5895: /**
5896: * Update a column with a character stream value.
5897: *
5898: * The updateXXX() methods are used to update column values in the current
5899: * row, or the insert row. The updateXXX() methods do not update the
5900: * underlying database, instead the updateRow() or insertRow() methods are
5901: * called to update the database.
5902: *
5903: * @param columnName
5904: * the name of the column
5905: * @param reader
5906: * the new column value
5907: * @param length
5908: * length of the stream
5909: * @exception SQLException
5910: * if a database-access error occurs
5911: */
5912: public void updateCharacterStream(String columnName, Reader reader,
5913: long length) throws SQLException {
5914: try {
5915: updateCharacterStream(findColumnX(columnName), reader,
5916: length);
5917: } catch (SqlException sqle) {
5918: throw sqle.getSQLException();
5919: }
5920: }
5921:
5922: /**
5923: * Updates the designated column using the given <code>Reader</code>
5924: * object.
5925: * The data will be read from the stream as needed until end-of-stream is
5926: * reached. The JDBC driver will do any necessary conversion from UNICODE
5927: * to the database char format.
5928: *
5929: * The updater methods are used to update column values in the current row
5930: * or the insert row. The updater methods do not update the underlying
5931: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5932: * methods are called to update the database.
5933: *
5934: * @param columnLabel the label for the column specified with the SQL AS
5935: * clause. If the SQL AS clause was not specified, then the label is
5936: * the name of the column
5937: * @param reader an object that contains the data to set the parameter
5938: * value to.
5939: * @throws SQLException if the columnIndex is not valid; if a database
5940: * access error occurs; the result set concurrency is
5941: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5942: * result set
5943: */
5944: public void updateClob(String columnLabel, Reader reader)
5945: throws SQLException {
5946: try {
5947: updateClob(findColumnX(columnLabel), reader);
5948: } catch (SqlException se) {
5949: throw se.getSQLException();
5950: }
5951: }
5952: }
|