Author: bernt Date: Fri Jun 2 07:25:48 2006 New Revision: 411167 URL: http://svn.apache.org/viewvc?rev=411167&view=rev Log: DERBY-1313: SUR: Use DRDA's extended diagnostic to send ROW_UPDATED and ROW_DELETED warnings. Submitted by Fernanda Pizzorno Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionRequest.java db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURQueryMixTest.java db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURTest.java Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java?rev=411167&r1=411166&r2=411167&view=diff ============================================================================== --- db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java (original) +++ db/derby/code/trunk/java/client/org/apache/derby/client/net/CodePoint.java Fri Jun 2 07:25:48 2006 @@ -153,6 +153,15 @@ // upon SQLSTATE 02000. static final int QRYCLSIMP_NO = 0x02; + // SQL Error Diagnostic Level + // DIAGLVL0 A null SQLDIAGGRP is returned. This is the default. + // DIAGLVL1 A non-null SQLDIAGGRP should be returned. + // DIAGLVL2 A non-null SQLDIAGGRP should be returned, and both SQLDCMSG + // message text fields should be returned as null strings. + static final byte DIAGLVL0 = (byte)0xF0; + static final byte DIAGLVL1 = (byte)0xF1; + static final byte DIAGLVL2 = (byte)0xF2; + // ----------------------ddm code points-------------------------------------- // Exchange Server Attributes. @@ -484,6 +493,9 @@ // XA Manager static final int XAMGR = 0x1C01; + + // SQL Error Diagnostic Level + static final int DIAGLVL = 0x2160; //-----------------------DDM reply codepoints--------------------------------- Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionRequest.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionRequest.java?rev=411167&r1=411166&r2=411167&view=diff ============================================================================== --- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionRequest.java (original) +++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnectionRequest.java Fri Jun 2 07:25:48 2006 @@ -395,6 +395,9 @@ typdef.isCcsidMbcSet(), typdef.getCcsidMbc()); + // This specifies the SQL Error Diagnostic Level + buildDIAGLVL(); + // RDB allow update is an optional parameter which indicates // whether the RDB allows the requester to perform update operations // in the RDB. If update operations are not allowed, this connection @@ -562,6 +565,13 @@ updateLengthBytes(); + } + + private void buildDIAGLVL() throws SqlException { + markLengthBytes(CodePoint.DIAGLVL); + + writeByte(CodePoint.DIAGLVL2); + updateLengthBytes(); } private void buildMGRLVLLS(int agent, Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java?rev=411167&r1=411166&r2=411167&view=diff ============================================================================== --- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java (original) +++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java Fri Jun 2 07:25:48 2006 @@ -33,8 +33,6 @@ import org.apache.derby.shared.common.reference.SQLState; import org.apache.derby.shared.common.sanity.SanityManager; -import org.apache.derby.shared.common.reference.SQLState; - public class NetCursor extends org.apache.derby.client.am.Cursor { NetResultSet netResultSet_; @@ -138,49 +136,51 @@ int[] columnDataComputedLength = null; boolean[] columnDataIsNull = null; boolean receivedDeleteHoleWarning = false; + boolean receivedRowUpdatedWarning = false; if ((position_ == lastValidBytePosition_) && (netResultSet_ != null) && (netResultSet_.scrollable_)) { return false; } - NetSqlca netSqlca = this.parseSQLCARD(qrydscTypdef_); - - if (netResultSet_ != null && netResultSet_.scrollable_) { - if (netSqlca != null && - netSqlca.getSqlState().equals(SQLState.ROW_DELETED)) { - receivedDeleteHoleWarning = true; - netSqlca = null; - } else { - setIsUpdataDeleteHole(rowIndex, false); - } - if (netSqlca != null && - netSqlca.getSqlState().equals(SQLState.ROW_UPDATED)) { - setIsRowUpdated(true); - netSqlca = null; - } else { - setIsRowUpdated(false); - } - } + NetSqlca[] netSqlca = this.parseSQLCARD(qrydscTypdef_); if (netSqlca != null) { - int sqlcode = netSqlca.getSqlCode(); - if (sqlcode < 0) { - throw new SqlException(netAgent_.logWriter_, netSqlca); - } else { - if (sqlcode > 0) { + for (int i=0;i 0) { + String sqlState = netSqlca[i].getSqlState(); + if (!sqlState.equals(SQLState.ROW_DELETED) && + !sqlState.equals(SQLState.ROW_UPDATED)) { + netResultSet_.accumulateWarning( + new SqlWarning(agent_.logWriter_, + netSqlca[i])); + } else { + receivedDeleteHoleWarning + |= sqlState.equals(SQLState.ROW_DELETED); + receivedRowUpdatedWarning + |= sqlState.equals(SQLState.ROW_UPDATED); } - } else if (netResultSet_ != null) { - netResultSet_.accumulateWarning(new SqlWarning(agent_.logWriter_, netSqlca)); } } } } + setIsUpdataDeleteHole(rowIndex, receivedDeleteHoleWarning); + setIsRowUpdated(receivedRowUpdatedWarning); + // If we don't have at least one byte in the buffer for the DA null indicator, // then we need to send a CNTQRY request to fetch the next block of data. // Read the DA null indicator. @@ -426,6 +426,28 @@ return i; } + // Reads 8-bytes from the dataBuffer from the current position. + // If position is already at the end of the buffer, send CNTQRY to get more + // data. + private long readFdocaLong() throws + org.apache.derby.client.am.DisconnectException, SqlException { + if ((position_ + 8) > lastValidBytePosition_) { + // Check for ENDQRYRM, throw SqlException if already received one. + checkAndThrowReceivedEndqryrm(); + + // Send CNTQRY to complete the row/rowset. + int lastValidByteBeforeFetch = completeSplitRow(); + + // if lastValidBytePosition_ has not changed, and an ENDQRYRM was + // received, throw a SqlException for the ENDQRYRM. + checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch); + } + + long i = SignedBinary.getLong(dataBuffer_, position_); + position_ += 8; + return i; + } + // Reads 1-byte from the dataBuffer from the current position. // If position is already at the end of the buffer, send CNTQRY to get more data. private int readFdocaOneByte() throws org.apache.derby.client.am.DisconnectException, SqlException { @@ -672,7 +694,7 @@ // // FORMAT FOR ALL SQLAM LEVELS // SQLCAGRP; GROUP LID 0x54; ELEMENT TAKEN 0(all); REP FACTOR 1 - NetSqlca parseSQLCARD(Typdef typdef) throws org.apache.derby.client.am.DisconnectException, SqlException { + NetSqlca[] parseSQLCARD(Typdef typdef) throws org.apache.derby.client.am.DisconnectException, SqlException { return parseSQLCAGRP(typdef); } @@ -691,7 +713,7 @@ // SQLERRPROC; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 8 // SQLCAXGRP; PROTOCOL TYPE N-GDA; ENVLID 0x52; Length Override 0 // SQLDIAGGRP; PROTOCOL TYPE N-GDA; ENVLID 0x56; Length Override 0 - private NetSqlca parseSQLCAGRP(Typdef typdef) throws org.apache.derby.client.am.DisconnectException, SqlException { + private NetSqlca[] parseSQLCAGRP(Typdef typdef) throws org.apache.derby.client.am.DisconnectException, SqlException { if (readFdocaOneByte() == CodePoint.NULLDATA) { return null; } @@ -702,9 +724,18 @@ parseSQLCAXGRP(typdef, netSqlca); - parseSQLDIAGGRP(); + NetSqlca[] sqlCa = parseSQLDIAGGRP(); - return netSqlca; + NetSqlca[] ret_val; + if (sqlCa != null) { + ret_val = new NetSqlca[sqlCa.length + 1]; + System.arraycopy(sqlCa, 0, ret_val, 1, sqlCa.length); + } else { + ret_val = new NetSqlca[1]; + } + ret_val[0] = netSqlca; + + return ret_val; } // SQLCAXGRP : EARLY FDOCA GROUP @@ -794,14 +825,154 @@ } // SQLDIAGGRP : FDOCA EARLY GROUP - private void parseSQLDIAGGRP() throws DisconnectException, SqlException { + private NetSqlca[] parseSQLDIAGGRP() throws DisconnectException, SqlException { + if (readFdocaOneByte() == CodePoint.NULLDATA) { + return null; + } + + parseSQLDIAGSTT(); + NetSqlca[] sqlca = parseSQLDIAGCI(); + parseSQLDIAGCN(); + + return sqlca; + } + + // SQL Diagnostics Statement Group Description - Identity 0xD3 + // NULLDATA will be received for now + private void parseSQLDIAGSTT() throws DisconnectException, SqlException { + if (readFdocaOneByte() == CodePoint.NULLDATA) { + return; + } + + // The server should send NULLDATA + netAgent_.accumulateChainBreakingReadExceptionAndThrow( + new DisconnectException(netAgent_, + new ClientMessageId(SQLState.DRDA_COMMAND_NOT_IMPLEMENTED), + "parseSQLDIAGSTT")); + } + + // SQL Diagnostics Condition Information Array - Identity 0xF5 + // SQLNUMROW; ROW LID 0x68; ELEMENT TAKEN 0(all); REP FACTOR 1 + // SQLDCIROW; ROW LID 0xE5; ELEMENT TAKEN 0(all); REP FACTOR 0(all) + private NetSqlca[] parseSQLDIAGCI() + throws DisconnectException, SqlException { + int num = readFdocaTwoByteLength(); // SQLNUMGRP - SQLNUMROW + NetSqlca[] ret_val = null; + if (num != 0) { + ret_val = new NetSqlca[num]; + } + + for (int i = 0; i < num; i++) { + ret_val[i] = parseSQLDCROW(); + } + return ret_val; + } + + // SQL Diagnostics Connection Array - Identity 0xF6 + // NULLDATA will be received for now + private void parseSQLDIAGCN() throws DisconnectException, SqlException { + if (readFdocaOneByte() == CodePoint.NULLDATA) { + return; + } + + // The server should send NULLDATA + netAgent_.accumulateChainBreakingReadExceptionAndThrow( + new DisconnectException(netAgent_, + new ClientMessageId(SQLState.DRDA_COMMAND_NOT_IMPLEMENTED), + "parseSQLDIAGCN")); + } + + // SQL Diagnostics Condition Group Description + // + // SQLDCCODE; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCSTATE; PROTOCOL TYPE FCS; ENVLID Ox30; Lengeh Override 5 + // SQLDCREASON; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCLINEN; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCROWN; PROTOCOL TYPE I8; ENVLID 0x16; Lengeh Override 8 + // SQLDCER01; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCER02; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCER03; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCER04; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCPART; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCPPOP; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 + // SQLDCMSGID; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 10 + // SQLDCMDE; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 8 + // SQLDCPMOD; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 5 + // SQLDCRDB; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 + // SQLDCTOKS; PROTOCOL TYPE N-RLO; ENVLID 0xF7; Length Override 0 + // SQLDCMSG_m; PROTOCOL TYPE NVMC; ENVLID 0x3F; Length Override 32672 + // SQLDCMSG_S; PROTOCOL TYPE NVCS; ENVLID 0x33; Length Override 32672 + // SQLDCCOLN_m; PROTOCOL TYPE NVCM ; ENVLID 0x3F; Length Override 255 + // SQLDCCOLN_s; PROTOCOL TYPE NVCS; ENVLID 0x33; Length Override 255 + // SQLDCCURN_m; PROTOCOL TYPE NVCM; ENVLID 0x3F; Length Override 255 + // SQLDCCURN_s; PROTOCOL TYPE NVCS; ENVLID 0x33; Length Override 255 + // SQLDCPNAM_m; PROTOCOL TYPE NVCM; ENVLID 0x3F; Length Override 255 + // SQLDCPNAM_s; PROTOCOL TYPE NVCS; ENVLID 0x33; Length Override 255 + // SQLDCXGRP; PROTOCOL TYPE N-GDA; ENVLID 0xD3; Length Override 1 + private NetSqlca parseSQLDCGRP() + throws DisconnectException, SqlException { + + int sqldcCode = readFdocaInt(); // SQLCODE + String sqldcState = readFdocaString(5, + netAgent_.targetTypdef_.getCcsidSbcEncoding()); // SQLSTATE + int sqldcReason = readFdocaInt(); // REASON_CODE + + skipFdocaBytes(12); // LINE_NUMBER + ROW_NUMBER + + NetSqlca sqlca = new NetSqlca(netAgent_.netConnection_, + sqldcCode, + sqldcState, + (byte[]) null); + + skipFdocaBytes(49); // SQLDCER01-04 + SQLDCPART + SQLDCPPOP + SQLDCMSGID + // SQLDCMDE + SQLDCPMOD + RDBNAME + parseSQLDCTOKS(); // MESSAGE_TOKENS + + String sqldcMsg = parseVCS(qrydscTypdef_); // MESSAGE_TEXT + + if (sqldcMsg != null) { + sqlca.setSqlerrmcBytes(sqldcMsg.getBytes(), + netAgent_.targetTypdef_.getByteOrder()); + } + + skipFdocaBytes(12); // COLUMN_NAME + PARAMETER_NAME + EXTENDED_NAMES + + parseSQLDCXGRP(); // SQLDCXGRP + return sqlca; + } + + // SQL Diagnostics Condition Row - Identity 0xE5 + // SQLDCGRP; GROUP LID 0xD5; ELEMENT TAKEN 0(all); REP FACTOR 1 + private NetSqlca parseSQLDCROW() throws DisconnectException, SqlException { + return parseSQLDCGRP(); + } + + // SQL Diagnostics Condition Token Array - Identity 0xF7 + // NULLDATA will be received for now + void parseSQLDCTOKS() throws DisconnectException, SqlException { + if (readFdocaOneByte() == CodePoint.NULLDATA) { + return; + } + + // The server should send NULLDATA + netAgent_.accumulateChainBreakingReadExceptionAndThrow( + new DisconnectException(netAgent_, + new ClientMessageId(SQLState.DRDA_COMMAND_NOT_IMPLEMENTED), + "parseSQLDCTOKS")); + } + + // SQL Diagnostics Extended Names Group Description - Identity 0xD5 + // NULLDATA will be received for now + private void parseSQLDCXGRP() throws DisconnectException, SqlException { if (readFdocaOneByte() == CodePoint.NULLDATA) { return; } - netAgent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(netAgent_, - new ClientMessageId(SQLState.DRDA_COMMAND_NOT_IMPLEMENTED), - "parseSQLDIAGGRP")); + // The server should send NULLDATA + netAgent_.accumulateChainBreakingReadExceptionAndThrow( + new DisconnectException(netAgent_, + new ClientMessageId(SQLState.DRDA_COMMAND_NOT_IMPLEMENTED), + "parseSQLDCXGRP")); } private String parseVCS(Typdef typdefInEffect) throws DisconnectException, SqlException { Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java?rev=411167&r1=411166&r2=411167&view=diff ============================================================================== --- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java (original) +++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/CodePoint.java Fri Jun 2 07:25:48 2006 @@ -490,6 +490,9 @@ // Number codepoint constant. static final int PKGNAMCSN = 0x2113; + // SQL Error Diagnostic Level + static final int DIAGLVL = 0x2160; + //-----------------------DDM reply codepoints--------------------------------- // Invalid description @@ -646,6 +649,15 @@ // in the QRYBLKSZ parameter, except for possibly the last // query block which may be shorter. static final int QRYBLKFLX = 0x01; + + // SQL Error Diagnostic Level + // DIAGLVL0 A null SQLDIAGGRP is returned. This is the default. + // DIAGLVL1 A non-null SQLDIAGGRP should be returned. + // DIAGLVL2 A non-null SQLDIAGGRP should be returned, and both SQLDCMSG + // message text fields should be returned as null strings. + static final byte DIAGLVL0 = (byte)0xF0; + static final byte DIAGLVL1 = (byte)0xF1; + static final byte DIAGLVL2 = (byte)0xF2; //----------------------------fdoca code points------------------------------- Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java?rev=411167&r1=411166&r2=411167&view=diff ============================================================================== --- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (original) +++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java Fri Jun 2 07:25:48 2006 @@ -124,6 +124,9 @@ private Database database; // pointer to the current database private int sqlamLevel; // SQLAM Level - determines protocol + // DRDA diagnostic level, DIAGLVL0 by default + private byte diagnosticLevel = (byte)0xF0; + // manager processing private Vector unknownManagers; private Vector knownManagers; @@ -2934,6 +2937,10 @@ case CodePoint.STTSTRDEL: codePointNotSupported(codePoint); break; + // optional + case CodePoint.DIAGLVL: + diagnosticLevel = reader.readByte(); + break; default: invalidCodePoint(codePoint); } @@ -5554,24 +5561,27 @@ private void writeSQLDIAGGRP(SQLException nextException) throws DRDAProtocolException { - writer.writeByte(CodePoint.NULLDATA); - return; + // for now we only want to send ROW_DELETED and ROW_UPDATED warnings + // as extended diagnostics + // move to first ROW_DELETED or ROW_UPDATED exception. These have been + // added to the end of the warning chain. + while ( + nextException != null && + nextException.getSQLState() != SQLState.ROW_UPDATED && + nextException.getSQLState() != SQLState.ROW_DELETED) { + nextException = nextException.getNextException(); + } - /** - * TODO: Enable the following code when JCC can support SQLDIAGGRP - * for all SQLCARD accesses. Commented out for now. - */ - /* - if (nextException == null) - { + if ((nextException == null) || + (diagnosticLevel == CodePoint.DIAGLVL0)) { writer.writeByte(CodePoint.NULLDATA); return; } + writer.writeByte(0); // SQLDIAGGRP indicator writeSQLDIAGSTT(); writeSQLDIAGCI(nextException); writeSQLDIAGCN(); - */ } /* @@ -5601,13 +5611,32 @@ while (se != null) { String sqlState = se.getSQLState(); - int sqlCode = getSqlCode(getExceptionSeverity(se)); + + // SQLCode > 0 -> Warning + // SQLCode = 0 -> Info + // SQLCode < 0 -> Error + int severity = getExceptionSeverity(se); + int sqlCode = -1; + if (severity == CodePoint.SVRCOD_WARNING) + sqlCode = 1; + else if (severity == CodePoint.SVRCOD_INFO) + sqlCode = 0; + String sqlerrmc = ""; - + if (diagnosticLevel == CodePoint.DIAGLVL1) { + sqlerrmc = se.getLocalizedMessage(); + } + // arguments are variable part of a message - Object[] args = ((EmbedSQLException)se).getArguments(); - for (int i = 0; args != null && i < args.length; i++) - sqlerrmc += args[i].toString() + SQLERRMC_TOKEN_DELIMITER; + // only send arguments for diagnostic level 0 + if (diagnosticLevel == CodePoint.DIAGLVL0) { + // we are only able to get arguments of EmbedSQLException + if (se instanceof EmbedSQLException) { + Object[] args = ((EmbedSQLException)se).getArguments(); + for (int i = 0; args != null && i < args.length; i++) + sqlerrmc += args[i].toString() + SQLERRMC_TOKEN_DELIMITER; + } + } String dbname = null; if (database != null) @@ -5618,7 +5647,6 @@ se = se.getNextException(); } - writer.writeByte(CodePoint.NULLDATA); return; } @@ -5648,7 +5676,7 @@ /* Count the number of chained exceptions to be sent */ for (se = nextException; se != null; se = se.getNextException()) i++; - writer.writeInt(i); + writer.writeShort(i); } /** @@ -6211,26 +6239,29 @@ SQLWarning sqlw = (rs != null)? rs.getWarnings(): null; // for updatable, insensitive result sets we signal the - // row updated condition to the client via a warning which - // is pushed on top of any other warnings on the result - // set, to be popped by client onto its rowUpdated state, - // i.e. this warning should not reach API level. + // row updated condition to the client via a warning to be + // popped by client onto its rowUpdated state, i.e. this + // warning should not reach API level. if (rs != null && rs.rowUpdated()) { - SQLWarning w = new SQLWarning(null, SQLState.ROW_UPDATED); + SQLWarning w = new SQLWarning(null, SQLState.ROW_UPDATED, + ExceptionSeverity.WARNING_SEVERITY); if (sqlw != null) { - w.setNextWarning(sqlw); - } - sqlw = w; + sqlw.setNextWarning(w); + } else { + sqlw = w; + } } // Delete holes are manifest as a row consisting of a non-null // SQLCARD and a null data group. The SQLCARD has a warning // SQLSTATE of 02502 if (rs != null && rs.rowDeleted()) { - SQLWarning w = new SQLWarning(null, SQLState.ROW_DELETED); + SQLWarning w = new SQLWarning(null, SQLState.ROW_DELETED, + ExceptionSeverity.WARNING_SEVERITY); if (sqlw != null) { - w.setNextWarning(sqlw); - } - sqlw = w; + sqlw.setNextWarning(w); + } else { + sqlw = w; + } } if (sqlw == null) Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURQueryMixTest.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURQueryMixTest.java?rev=411167&r1=411166&r2=411167&view=diff ============================================================================== --- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURQueryMixTest.java (original) +++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURQueryMixTest.java Fri Jun 2 07:25:48 2006 @@ -364,8 +364,7 @@ "forward.", rows.get(new Integer(i)), rowString); - if (checkRowUpdated && updatedRows.contains(new Integer(i)) && - !deletedRows.contains(new Integer(i))) { + if (checkRowUpdated && updatedRows.contains(new Integer(i))) { assertTrue("Expected rs.rowUpdated() to return true on " + "updated row " + rowString, rs.rowUpdated()); } @@ -385,8 +384,7 @@ " when navigating forward.", rows.get(new Integer(i)), rowString); - if (checkRowUpdated && updatedRows.contains(new Integer(i)) && - !deletedRows.contains(new Integer(i))) { + if (checkRowUpdated && updatedRows.contains(new Integer(i))) { assertTrue("Expected rs.rowUpdated() to return true on " + "updated row " + rowString, rs.rowUpdated()); } Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURTest.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURTest.java?rev=411167&r1=411166&r2=411167&view=diff ============================================================================== --- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURTest.java (original) +++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURTest.java Fri Jun 2 07:25:48 2006 @@ -1258,6 +1258,36 @@ /** + * Test that rowUpdated() and rowDeleted() methods both return true when + * the row has first been updated and then deleted using the updateRow() + * and deleteRow() methods. + */ + public void testRowUpdatedAndRowDeleted() throws SQLException { + Statement s = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE); + s.setCursorName(getNextCursorName()); + ResultSet rs = s.executeQuery("select a,b from t1"); + rs.next(); + rs.updateInt(1, rs.getInt(1) + 2 * recordCount); + rs.updateRow(); + assertTrue("Expected rowUpdated() to return true", rs.rowUpdated()); + rs.deleteRow(); + rs.next(); + rs.previous(); + assertTrue("Expected rowUpdated() to return true", rs.rowUpdated()); + assertTrue("Expected rowDeleted() to return true", rs.rowDeleted()); + rs.next(); + assertFalse("Expected rowUpdated() to return false", rs.rowUpdated()); + assertFalse("Expected rowDeleted() to return false", rs.rowDeleted()); + rs.previous(); + assertTrue("Expected rowUpdated() to return true", rs.rowUpdated()); + assertTrue("Expected rowDeleted() to return true", rs.rowDeleted()); + rs.close(); + s.close(); + } + + + /** * Test that the JDBC detectability calls throw correct exceptions when * called in in wrong row states. * This is done for both supported updatable result set types.