You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by lv...@apache.org on 2008/03/04 07:43:27 UTC

svn commit: r633371 - in /harmony/enhanced/classlib/trunk/modules/sql/src: main/java/org/apache/harmony/sql/internal/rowset/ test/java/org/apache/harmony/sql/tests/internal/rowset/

Author: lvjing
Date: Mon Mar  3 22:43:19 2008
New Revision: 633371

URL: http://svn.apache.org/viewvc?rev=633371&view=rev
Log:
Apply patch for HARMONY-5564 ([classlib][sql] add support for detecting multi-conflicts when write data back)

Modified:
    harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRow.java
    harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetImpl.java
    harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetWriter.java
    harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/SyncResolverImpl.java
    harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetImplTest.java
    harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetUpdateTest.java
    harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/SyncResolverTest.java

Modified: harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRow.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRow.java?rev=633371&r1=633370&r2=633371&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRow.java (original)
+++ harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRow.java Mon Mar  3 22:43:19 2008
@@ -130,6 +130,14 @@
         originalColumnData = columnData.clone();
     }
 
+    public void restoreOriginal() {
+        isUpdate = false;
+        isDelete = false;
+        isInsert = false;
+        mask.flip(0, columnData.length);
+        columnData = originalColumnData.clone();
+    }
+
     public Object getObject(int columnIndex) {
         return columnData[columnIndex - 1];
     }

Modified: harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetImpl.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetImpl.java?rev=633371&r1=633370&r2=633371&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetImpl.java (original)
+++ harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetImpl.java Mon Mar  3 22:43:19 2008
@@ -173,14 +173,16 @@
 
     public void acceptChanges() throws SyncProviderException {
         if (currentRow == insertRow && currentRow != null) {
+            // TODO add error messages
             throw new SyncProviderException();
         }
 
         try {
             acceptChanges(getConnection());
         } catch (SQLException e) {
-            // FIXME deal with the exception, not just print it
-            e.printStackTrace();
+            SyncProviderException ex = new SyncProviderException();
+            ex.initCause(e);
+            throw ex;
         }
     }
 
@@ -197,21 +199,59 @@
             int beforeWriteIndex = currentRowIndex;
             rowSetWriter.writeData(this);
             absolute(beforeWriteIndex);
+
+            boolean isChanged = false;
             /*
              * FIXME: if no conflicts happen when writeData, then call
              * setOriginalRow()
              */
+            for (int i = rows.size() - 1; i >= 0; i--) {
+                currentRow = rows.get(i);
+                if (rowDeleted()) {
+                    isChanged = true;
+                    setOriginalRow();
+                } else if (rowInserted() || rowUpdated()) {
+                    isChanged = true;
+                    setOriginalRow();
+                }
+            }
+            // Set originalResultSet
+            if (isChanged) {
+                try {
+                    ArrayList<CachedRow> nowRows = new ArrayList<CachedRow>();
+                    for (int i = 0; i < rows.size(); i++) {
+                        nowRows.add(rows.get(i).createClone());
+                        nowRows.get(i).restoreOriginal();
+                    }
+                    originalResultSet.setRows(nowRows, columnCount);
+                } catch (CloneNotSupportedException cloneE) {
+                    // TODO how to deal with the CloneNotSupportedException
+                    throw new SyncProviderException(cloneE.getMessage());
+                }
+            }
+
+            if (currentRowIndex > rows.size()) {
+                afterLast();
+            } else if (currentRowIndex <= 0) {
+                beforeFirst();
+            } else {
+                absolute(currentRowIndex);
+            }
+
             notifyRowSetChanged();
 
         } catch (SyncProviderException e) {
             throw e;
         } catch (SQLException e) {
-            throw new SyncProviderException(e.getMessage());
+            SyncProviderException ex = new SyncProviderException();
+            ex.initCause(e);
+            throw ex;
         }
     }
 
     public boolean columnUpdated(int idx) throws SQLException {
-        if (currentRow == null || idx > meta.getColumnCount()) {
+        if (currentRow == null || idx > meta.getColumnCount() || idx <= 0
+                || currentRow == insertRow) {
             // rowset.0 = Not a valid position
             throw new SQLException(Messages.getString("rowset.0")); //$NON-NLS-1$
         }
@@ -558,13 +598,16 @@
     }
 
     public void setOriginalRow() throws SQLException {
-
-        // FIXME re-implements this method
         if (currentRow == null) {
             // TODO add error messages
             throw new SQLException();
         }
-        currentRow.setNonUpdateable();
+
+        if (rowDeleted()) {
+            rows.remove(currentRow);
+        } else if (rowUpdated() || rowInserted()) {
+            currentRow.setOriginal();
+        }
     }
 
     public void setPageSize(int size) throws SQLException {
@@ -625,7 +668,16 @@
     }
 
     public void undoUpdate() throws SQLException {
-        throw new NotImplementedException();
+        if (currentRow == null) {
+            // TODO add error message
+            throw new SQLException();
+        }
+
+        if (currentRow == insertRow) {
+            currentRow = new CachedRow(new Object[columnCount]);
+        } else if (rowUpdated()) {
+            currentRow.restoreOriginal();
+        }
     }
 
     public int[] getMatchColumnIndexes() throws SQLException {
@@ -683,6 +735,7 @@
      * @throws SQLException
      */
     private boolean doAbsolute(int row, boolean checkType) throws SQLException {
+        // FIXME need to consider getShowDeleted()
         if (rows == null || rows.size() == 0) {
             return false;
         }
@@ -726,7 +779,14 @@
     }
 
     public void cancelRowUpdates() throws SQLException {
-        throw new NotImplementedException();
+        if (currentRow == null || currentRow == insertRow) {
+            // TODO add error message
+            throw new SQLException();
+        }
+
+        if (rowUpdated()) {
+            currentRow.restoreOriginal();
+        }
     }
 
     public void clearWarnings() throws SQLException {
@@ -747,6 +807,10 @@
 
     public void deleteRow() throws SQLException {
         checkValidRow();
+        if (currentRow == insertRow) {
+            // TODO add error message
+            throw new SQLException();
+        }
         currentRow.setDelete();
     }
 
@@ -1169,7 +1233,6 @@
 
     public boolean rowDeleted() throws SQLException {
         checkValidRow();
-        checkCursorValid();
         return currentRow.isDelete();
     }
 
@@ -1182,6 +1245,12 @@
     }
 
     public boolean rowUpdated() throws SQLException {
+
+        if (currentRow == null || currentRow == insertRow) {
+            // TODO add error message
+            throw new SQLException();
+        }
+
         if (!currentRow.isUpdate()) {
             return false;
         }
@@ -1439,11 +1508,11 @@
      */
     private Object convertUpdateValue(int columnIndex, Object value)
             throws SQLException {
-        
+
         if (value == null) {
             return value;
         }
-        
+
         Class type = columnTypes[columnIndex - 1];
 
         /*

Modified: harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetWriter.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetWriter.java?rev=633371&r1=633370&r2=633371&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetWriter.java (original)
+++ harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/CachedRowSetWriter.java Mon Mar  3 22:43:19 2008
@@ -25,6 +25,7 @@
 import javax.sql.RowSetWriter;
 import javax.sql.rowset.CachedRowSet;
 import javax.sql.rowset.spi.SyncProviderException;
+import javax.sql.rowset.spi.SyncResolver;
 
 public class CachedRowSetWriter implements RowSetWriter {
 
@@ -40,6 +41,8 @@
 
     private int columnCount;
 
+    private SyncResolverImpl resolver;
+
     public void setConnection(Connection conn) {
         originalConnection = conn;
     }
@@ -56,30 +59,49 @@
         // analyse every row and do responsible task.
         currentRowSet.beforeFirst();// currentRowSet.first();
         originalRowSet.beforeFirst();// originalRowSet.first();
+        resolver = null;
         while (currentRowSet.next()) {
             if (currentRowSet.rowInserted()) {
-                insertCurrentRow();
+                try {
+                    insertCurrentRow();
+                } catch (SyncProviderException e) {
+                    addConflict(SyncResolver.INSERT_ROW_CONFLICT);
+                }
             } else if (currentRowSet.rowDeleted()) {
                 if (isConflictExistForCurrentRow()) {
-                    // TODO: conflict exists, should throw SyncProviderException
-                    throw new SyncProviderException();
+                    addConflict(SyncResolver.DELETE_ROW_CONFLICT);
                 }
 
                 deleteCurrentRow();
 
             } else if (currentRowSet.rowUpdated()) {
                 if (isConflictExistForCurrentRow()) {
-                    // TODO: conflict exists, should throw SyncProviderException
-                    throw new SyncProviderException();
+                    addConflict(SyncResolver.UPDATE_ROW_CONFLICT);
+                }
+                try {
+                    updateCurrentRow();
+                } catch (SyncProviderException e) {
+                    addConflict(SyncResolver.UPDATE_ROW_CONFLICT);
                 }
-                
-                updateCurrentRow();
             }
         }
+
+        if (resolver != null) {
+            throw new SyncProviderException(resolver);
+        }
         // TODO release resource
         return true;
     }
 
+    private void addConflict(int status) throws SQLException {
+        if (resolver == null) {
+            resolver = new SyncResolverImpl(currentRowSet.getMetaData());
+        }
+
+        resolver.addConflictRow(new CachedRow(new Object[columnCount]),
+                currentRowSet.getRow(), status);
+    }
+
     /**
      * Insert the RowSet's current row to DB
      * 
@@ -126,7 +148,6 @@
         try {
             preSt.executeUpdate();
         } catch (SQLException e) {
-            // TODO generate SyncProviderException
             throw new SyncProviderException();
         } finally {
             preSt.close();
@@ -207,7 +228,6 @@
         try {
             preSt.executeUpdate();
         } catch (SQLException e) {
-            // TODO generate SyncProviderException
             throw new SyncProviderException();
         } finally {
             preSt.close();

Modified: harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/SyncResolverImpl.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/SyncResolverImpl.java?rev=633371&r1=633370&r2=633371&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/SyncResolverImpl.java (original)
+++ harmony/enhanced/classlib/trunk/modules/sql/src/main/java/org/apache/harmony/sql/internal/rowset/SyncResolverImpl.java Mon Mar  3 22:43:19 2008
@@ -58,7 +58,7 @@
 
     private int currentIndex;
 
-    private RowSetMetaData metadata;
+    private ResultSetMetaData metadata;
 
     private static class ConflictedRow {
         CachedRow row;
@@ -74,7 +74,7 @@
         }
     }
 
-    public SyncResolverImpl(RowSetMetaData metadata) {
+    public SyncResolverImpl(ResultSetMetaData metadata) {
         super();
         this.metadata = metadata;
         conflictRows = new ArrayList<ConflictedRow>();

Modified: harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetImplTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetImplTest.java?rev=633371&r1=633370&r2=633371&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetImplTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetImplTest.java Mon Mar  3 22:43:19 2008
@@ -34,6 +34,7 @@
 import javax.sql.RowSetMetaData;
 import javax.sql.rowset.CachedRowSet;
 import javax.sql.rowset.spi.SyncProviderException;
+import javax.sql.rowset.spi.SyncResolver;
 
 public class CachedRowSetImplTest extends CachedRowSetTestCase {
 
@@ -76,6 +77,62 @@
         // assertEquals("update3", originalRow.getString(2));
     }
 
+    public void testSetOriginalRow() throws Exception {
+        /*
+         * According to the spec, this method is called internally after the any
+         * modified values in the current row have been synchronized with the
+         * data source.
+         */
+        crset.beforeFirst();
+        assertTrue(crset.absolute(3));
+        crset.updateString(2, "update3");
+        // NOTICE: though update the column here, updateRow() isn't called.
+
+        assertTrue(crset.next());
+        crset.deleteRow();
+        crset.acceptChanges(conn);
+
+        // DB
+        rs = st.executeQuery("select * from user_info");
+        int index = 0;
+        while (rs.next()) {
+            index++;
+            assertEquals(index, rs.getInt(1));
+            if (index == 3) {
+                assertEquals("test3", rs.getString(2));
+            }
+        }
+        assertEquals(3, index);
+        // CachedRowSet
+        crset.beforeFirst();
+        index = 0;
+        while (crset.next()) {
+            index++;
+            assertEquals(index, crset.getInt(1));
+            if (index == 3) {
+                assertEquals("update3", crset.getString(2));
+            }
+        }
+        assertEquals(3, index);
+
+        // move to the third row, call updateRow() again
+        assertTrue(crset.absolute(3));
+        crset.updateRow();
+        crset.acceptChanges(conn);
+        // Compare DB and CachedRowSet
+        rs = st.executeQuery("select * from user_info");
+        // CachedRowSet
+        crset.beforeFirst();
+        index = 0;
+        while (crset.next() && rs.next()) {
+            index++;
+            assertEquals(index, rs.getInt(1));
+            if (index == 3) {
+                assertEquals("update3", rs.getString(2));
+            }
+        }
+    }
+
     public void testSetSyncProvider() throws Exception {
         if (System.getProperty("Testing Harmony") == "true") {
             String mySyncProvider = "org.apache.harmony.sql.internal.rowset.HYOptimisticProvider";
@@ -85,48 +142,6 @@
         }
     }
 
-    public void testColumnUpdatedInt() throws SQLException {
-        crset.first();
-        // try {
-        // assertFalse(crset.columnUpdated(1));
-        // fail("should throw SQLException");
-        // } catch (SQLException e) {
-        // // expected;
-        // }
-        crset.next();
-        try {
-            crset.columnUpdated(-1);
-            fail("should throw IndexOutOfBoundsException");
-        } catch (IndexOutOfBoundsException e) {
-            // expected;
-        }
-        try {
-            crset.columnUpdated(0);
-            fail("should throw IndexOutOfBoundsException");
-        } catch (IndexOutOfBoundsException e) {
-            // expected;
-        }
-        assertFalse(crset.columnUpdated(1));
-    }
-
-    public void testColumnUpdatedString() throws SQLException {
-        crset.first();
-        // try {
-        // assertFalse(crset.columnUpdated("ID"));
-        // fail("should throw SQLException");
-        // } catch (SQLException e) {
-        // // expected;
-        // }
-        crset.next();
-        try {
-            assertFalse(crset.columnUpdated("Incorrect"));
-            fail("should throw SQLException");
-        } catch (SQLException e) {
-            // expected;
-        }
-        assertFalse(crset.columnUpdated("NAME"));
-    }
-
     public void testGetPageSize() throws SQLException {
         assertEquals(0, crset.getPageSize());
         crset.setPageSize(1);
@@ -146,7 +161,6 @@
     }
 
     public void testGetTableName() throws SQLException {
-
         crset.setTableName("USER");
         assertEquals("USER", crset.getTableName());
     }
@@ -166,57 +180,154 @@
         assertEquals(0, noInitialCrset.size());
     }
 
-    public void testDeleteRow() throws SQLException {
-        crset.first();
-        // try {
-        // crset.deleteRow();
-        // fail("should throw SQLException");
-        // } catch (SQLException e) {
-        // // expected;
-        // }
-        crset.next();
-        assertFalse(crset.rowDeleted());
-        crset.deleteRow();
-        assertEquals(DEFAULT_ROW_COUNT, crset.size());
-        assertTrue(crset.rowDeleted());
+    public void testDeleteRow_Exception() throws Exception {
+        /*
+         * This method is mainly used to test exception
+         */
+        noInitialCrset = newNoInitialInstance();
+        try {
+            noInitialCrset.deleteRow();
+            fail("should throw SQLException");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // RI would throw ArrayIndexOutOfBoundsException
+        } catch (SQLException e) {
+            // according to spec, it's supposed to throw SQLException
+        }
+
+        rs = st.executeQuery("SELECT * FROM USER_INFO");
+        noInitialCrset.populate(rs);
+
+        try {
+            noInitialCrset.deleteRow();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.moveToInsertRow();
+        try {
+            noInitialCrset.deleteRow();
+            fail("should throw SQLException");
+        } catch (ClassCastException e) {
+            // RI would throw ClassCastException
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.moveToCurrentRow();
+        assertTrue(noInitialCrset.absolute(4));
+        assertEquals(4, noInitialCrset.getInt(1));
+        noInitialCrset.deleteRow();
+        noInitialCrset.acceptChanges(conn);
+        // check the cursor position after delete
+        assertTrue(noInitialCrset.isAfterLast());
+
+        // check DB
+        rs = st.executeQuery("SELECT COUNT(*) FROM USER_INFO WHERE ID = 4");
+        assertTrue(rs.next());
+        assertEquals(0, rs.getInt(1));
+
+        // check CachedRowSet
+        noInitialCrset.beforeFirst();
+        int index = 0;
+        while (noInitialCrset.next()) {
+            index++;
+            assertEquals(index, noInitialCrset.getInt(1));
+        }
+        assertEquals(3, index);
     }
 
-    public void testRowDeleted() throws SQLException {
-        // try {
-        // crset.rowDeleted();
-        // fail("should throw SQLException");
-        // } catch (SQLException e) {
-        // // expected;
-        // }
+    public void testDeleteRow_CursorPos() throws Exception {
+        /*
+         * This method is mainly used to test cursor position after delete
+         */
+        insertMoreData(5);
+        rs = st.executeQuery("SELECT * FROM USER_INFO");
+        noInitialCrset = newNoInitialInstance();
+        noInitialCrset.populate(rs);
+
+        /*
+         * move to the fifth row, then delete it, check the cursor position
+         */
+        assertTrue(noInitialCrset.absolute(5));
+        assertEquals(5, noInitialCrset.getInt(1));
+        noInitialCrset.deleteRow();
+        noInitialCrset.acceptChanges(conn);
+        // the cursor is on the sixth row now, that is move to the next row
+        assertEquals(6, noInitialCrset.getInt(1));
+        assertTrue(noInitialCrset.absolute(5));
+        assertEquals(6, noInitialCrset.getInt(1));
+
+        /*
+         * Delete the sixth row. Then move the cursor to the seventh row. Check
+         * the cursor position after delete.
+         */
+        noInitialCrset.deleteRow();
+        assertTrue(noInitialCrset.next());
+        assertEquals(7, noInitialCrset.getInt(1));
+        noInitialCrset.acceptChanges(conn);
+        /*
+         * We can see the cursor is on the eighth row now.
+         */
+        assertEquals(8, noInitialCrset.getInt(1));
+
+        /*
+         * Delete the row before the last row. Then move the cursor to the last
+         * row before call acceptChanges(). Check the cursor position after
+         * delete.
+         */
+        assertTrue(noInitialCrset.last());
+        assertTrue(noInitialCrset.previous());
+        assertEquals(9, noInitialCrset.getInt(1));
+        noInitialCrset.deleteRow();
+        assertTrue(noInitialCrset.last());
+        assertEquals(10, noInitialCrset.getInt(1));
+        noInitialCrset.acceptChanges(conn);
+        assertTrue(noInitialCrset.isAfterLast());
     }
 
-    public void testInsertRow() throws SQLException {
-        crset.first();
+    public void testDeleteRow_MultiDel() throws Exception {
+        insertMoreData(5);
+        rs = st.executeQuery("SELECT * FROM USER_INFO");
+        noInitialCrset = newNoInitialInstance();
+        noInitialCrset.populate(rs);
+
+        assertTrue(noInitialCrset.absolute(3));
+        noInitialCrset.deleteRow(); // delete the third row
+        assertTrue(noInitialCrset.next());
+        noInitialCrset.deleteRow(); // delete the fourth row
+        assertTrue(noInitialCrset.next());
+        noInitialCrset.deleteRow(); // delete the fifth row
+        assertTrue(noInitialCrset.first());
+        noInitialCrset.acceptChanges(conn);
+        assertEquals(1, noInitialCrset.getInt(1));
+    }
+
+    public void testRowDeleted() throws Exception {
+        noInitialCrset = newNoInitialInstance();
         try {
-            crset.insertRow();
+            noInitialCrset.rowDeleted();
             fail("should throw SQLException");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // RI would throw ArrayIndexOutOfBoundsException
         } catch (SQLException e) {
-            // expected;
+            // according to spec, it's supposed to throw SQLException
         }
-        crset.next();
+
+        rs = st.executeQuery("SELECT * FROM USER_INFO");
+        noInitialCrset.populate(rs);
+
         try {
-            crset.insertRow();
+            noInitialCrset.rowDeleted();
             fail("should throw SQLException");
         } catch (SQLException e) {
-            // expected;
+            // expected
         }
-        crset.moveToInsertRow();
-        crset.updateString("Name", "TonyWu");
-        crset.updateInt("ID", 3);
-        crset.insertRow();
-        assertEquals("TonyWu", crset.getString(2));
-        assertEquals("TonyWu", crset.getString("Name"));
-        assertEquals(3, crset.getInt(1));
-        assertEquals(3, crset.getInt("ID"));
-
-        crset.moveToCurrentRow();
-        assertFalse(crset.rowInserted());
 
+        assertTrue(noInitialCrset.next());
+        assertFalse(noInitialCrset.rowDeleted());
+        noInitialCrset.deleteRow();
+        assertTrue(noInitialCrset.rowDeleted());
     }
 
     public void testAcceptChanges() throws SQLException {
@@ -847,7 +958,27 @@
             crset.acceptChanges(conn);
             fail("Should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // expected, TODO test SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            assertTrue(resolver.nextConflict());
+            assertEquals(3, resolver.getRow());
+
+            assertEquals(SyncResolver.UPDATE_ROW_CONFLICT, resolver.getStatus());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            assertFalse(resolver.nextConflict());
         }
 
         assertEquals("updated", copy.getString(2));
@@ -1147,7 +1278,7 @@
         assertEquals(ResultSet.CONCUR_UPDATABLE, noInitialCrset
                 .getConcurrency());
         assertEquals(0, crset.getRow());
-        
+
         // TODO uncomment after impelemented
         // try {
         // crset.getCursorName();
@@ -1466,7 +1597,35 @@
             crset.acceptChanges(conn);
             fail("should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // TODO analysis SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            assertTrue(resolver.nextConflict());
+            /*
+             * TODO no-bug different, ri insert row after current row, Harmony
+             * insert row after last row
+             */
+            if ("true".equals(System.getProperty("Testing Harmony"))) {
+                assertEquals(5, resolver.getRow());
+            } else {
+                assertEquals(1, resolver.getRow());
+            }
+
+            assertEquals(SyncResolver.INSERT_ROW_CONFLICT, resolver.getStatus());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            assertFalse(resolver.nextConflict());
         }
 
         /*
@@ -1487,7 +1646,35 @@
             crset.acceptChanges(conn);
             fail("should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // TODO analysis SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            assertTrue(resolver.nextConflict());
+            /*
+             * TODO no-bug different, ri insert row after current row, Harmony
+             * insert row after last row
+             */
+            if ("true".equals(System.getProperty("Testing Harmony"))) {
+                assertEquals(5, resolver.getRow());
+            } else {
+                assertEquals(1, resolver.getRow());
+            }
+
+            assertEquals(SyncResolver.INSERT_ROW_CONFLICT, resolver.getStatus());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            assertFalse(resolver.nextConflict());
         }
 
         /*
@@ -1545,7 +1732,35 @@
             crset.acceptChanges(conn);
             fail("should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // TODO analysis SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            assertTrue(resolver.nextConflict());
+            /*
+             * TODO no-bug different, ri insert row after current row, Harmony
+             * insert row after last row
+             */
+            if ("true".equals(System.getProperty("Testing Harmony"))) {
+                assertEquals(5, resolver.getRow());
+            } else {
+                assertEquals(1, resolver.getRow());
+            }
+
+            assertEquals(SyncResolver.INSERT_ROW_CONFLICT, resolver.getStatus());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            assertFalse(resolver.nextConflict());
         }
     }
 
@@ -1560,6 +1775,8 @@
         while (crset.next()) {
             crset.deleteRow();
         }
+
+        // TODO maybe RI's bug
         if ("true".equals(System.getProperty("Testing Harmony"))) {
             crset.acceptChanges(conn);
         } else {
@@ -1597,7 +1814,27 @@
             crset.acceptChanges(conn);
             fail("should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // TODO analysis SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            assertTrue(resolver.nextConflict());
+            assertEquals(3, resolver.getRow());
+
+            assertEquals(SyncResolver.DELETE_ROW_CONFLICT, resolver.getStatus());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            assertFalse(resolver.nextConflict());
         }
 
         /*
@@ -1618,7 +1855,28 @@
             crset.acceptChanges(conn);
             fail("should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // TODO analysis SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            // TODO resolver doesn't contian conflict in RI, maybe RI's bug
+            if ("true".equals(System.getProperty("Testing Harmony"))) {
+                assertTrue(resolver.nextConflict());
+
+                for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                    // all values are null
+                    assertNull(resolver.getConflictValue(i));
+                }
+
+            } else {
+                assertFalse(resolver.nextConflict());
+            }
         }
     }
 
@@ -1676,7 +1934,27 @@
             crset.acceptChanges(conn);
             fail("should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // TODO analysis SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            assertTrue(resolver.nextConflict());
+            assertEquals(3, resolver.getRow());
+
+            assertEquals(SyncResolver.UPDATE_ROW_CONFLICT, resolver.getStatus());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            assertFalse(resolver.nextConflict());
         }
 
         /*
@@ -1698,7 +1976,30 @@
             crset.acceptChanges(conn);
             fail("should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // TODO analysis SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            assertTrue(resolver.nextConflict());
+            assertEquals(3, resolver.getRow());
+
+            assertEquals(SyncResolver.UPDATE_ROW_CONFLICT, resolver.getStatus());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                try {
+                    resolver.getConflictValue(i);
+                } catch (SQLException ex) {
+                    // TODO RI throw SQLException here, maybe RI's bug
+                }
+            }
+
+            assertFalse(resolver.nextConflict());
         }
 
         /*
@@ -1720,7 +2021,127 @@
             crset.acceptChanges(conn);
             fail("should throw SyncProviderException");
         } catch (SyncProviderException e) {
-            // TODO analysis SyncProviderException
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            assertTrue(resolver.nextConflict());
+            assertEquals(3, resolver.getRow());
+
+            assertEquals(SyncResolver.UPDATE_ROW_CONFLICT, resolver.getStatus());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            assertFalse(resolver.nextConflict());
+        }
+    }
+
+    public void testAcceptChanges_MultiConflicts() throws Exception {
+        /*
+         * Update a row in which one column's value is out of range
+         */
+        assertTrue(crset.absolute(3));
+        assertEquals(3, crset.getInt(1));
+        crset.updateString(2, "update4");
+        crset.updateLong(3, 555555L);
+        crset.updateInt(4, 200000); // 200000 exceeds the NUMERIC's range
+        crset.updateBigDecimal(5, new BigDecimal(23));
+        crset.updateFloat(8, 4.888F);
+        crset.updateRow();
+
+        /*
+         * Delete a row which has been deleted from database
+         */
+        int result = st.executeUpdate("delete from USER_INFO where ID = 1");
+        assertEquals(1, result);
+        // move to the first row which doesn't exist in database
+        assertTrue(crset.absolute(1));
+        assertEquals(1, crset.getInt(1));
+        crset.deleteRow();
+
+        /*
+         * Insert a new row. One given column's value exceeds the max range.
+         * Therefore, it should throw SyncProviderException.
+         */
+        assertTrue(crset.last());
+        crset.moveToInsertRow();
+        crset.updateInt(1, 5);
+        crset.updateString(2, "test5");
+        crset.updateLong(3, 555555L);
+        crset.updateInt(4, 200000); // 200000 exceeds the NUMERIC's range
+        crset.updateBigDecimal(5, new BigDecimal(23));
+        crset.updateFloat(8, 4.888F);
+        crset.insertRow();
+        crset.moveToCurrentRow();
+
+        try {
+            crset.acceptChanges(conn);
+        } catch (SyncProviderException e) {
+            SyncResolver resolver = e.getSyncResolver();
+            assertEquals(0, resolver.getRow());
+
+            try {
+                resolver.getConflictValue(1);
+                fail("Should throw SQLException");
+            } catch (SQLException ex) {
+                // expected, Invalid cursor position
+            }
+
+            HashMap<Integer, Integer> conflicts = new HashMap<Integer, Integer>();
+            conflicts.put(SyncResolver.INSERT_ROW_CONFLICT, 5);
+            conflicts.put(SyncResolver.UPDATE_ROW_CONFLICT, 3);
+            conflicts.put(SyncResolver.DELETE_ROW_CONFLICT, 1);
+
+            assertTrue(resolver.nextConflict());
+
+            assertTrue(conflicts.containsKey(resolver.getStatus()));
+            assertEquals(((Integer) conflicts.get(resolver.getStatus()))
+                    .intValue(), resolver.getRow());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            assertTrue(resolver.nextConflict());
+
+            assertTrue(conflicts.containsKey(resolver.getStatus()));
+            assertEquals(((Integer) conflicts.get(resolver.getStatus()))
+                    .intValue(), resolver.getRow());
+
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                // all values are null
+                assertNull(resolver.getConflictValue(i));
+            }
+
+            // TODO RI only contains two conflicts, maybe RI's bug
+            if ("true".equals(System.getProperty("Testing Harmony"))) {
+                assertTrue(resolver.nextConflict());
+
+                assertTrue(conflicts.containsKey(resolver.getStatus()));
+                assertEquals(((Integer) conflicts.get(resolver.getStatus()))
+                        .intValue(), resolver.getRow());
+
+                for (int i = 1; i <= DEFAULT_COLUMN_COUNT; ++i) {
+                    // all values are null
+                    assertNull(resolver.getConflictValue(i));
+                }
+
+                assertFalse(resolver.nextConflict());
+
+            } else {
+                assertFalse(resolver.nextConflict());
+            }
+
         }
     }
 

Modified: harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetUpdateTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetUpdateTest.java?rev=633371&r1=633370&r2=633371&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetUpdateTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/CachedRowSetUpdateTest.java Mon Mar  3 22:43:19 2008
@@ -28,6 +28,342 @@
 import javax.sql.rowset.spi.SyncProviderException;
 
 public class CachedRowSetUpdateTest extends CachedRowSetTestCase {
+
+    public void testColumnUpdated() throws Exception {
+        noInitialCrset = newNoInitialInstance();
+        try {
+            noInitialCrset.columnUpdated(1);
+            fail("should throw exception");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // RI throw ArrayIndexOutOfBoundsException
+        } catch (SQLException e) {
+            // According to spec, it's supposed to throw SQLException
+        }
+
+        rs = st.executeQuery("SELECT * FROM USER_INFO");
+        noInitialCrset.populate(rs);
+
+        // the cursor is before the first row
+        assertTrue(noInitialCrset.isBeforeFirst());
+        try {
+            noInitialCrset.columnUpdated("ID");
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        // the cursor is after the last row
+        noInitialCrset.afterLast();
+        assertTrue(noInitialCrset.isAfterLast());
+        try {
+            noInitialCrset.columnUpdated(1);
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        assertTrue(noInitialCrset.first());
+        noInitialCrset.moveToInsertRow();
+        try {
+            noInitialCrset.columnUpdated("NAME");
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.moveToCurrentRow();
+        assertTrue(noInitialCrset.absolute(3));
+        assertEquals(3, noInitialCrset.getInt(1));
+        assertFalse(noInitialCrset.columnUpdated(2));
+        noInitialCrset.updateString(2, "update3");
+        assertTrue(noInitialCrset.columnUpdated(2));
+        noInitialCrset.acceptChanges(conn);
+
+        assertTrue(noInitialCrset.absolute(3));
+        assertEquals(3, noInitialCrset.getInt(1));
+        assertTrue(noInitialCrset.columnUpdated("NAME"));
+
+        noInitialCrset.updateRow();
+        noInitialCrset.acceptChanges(conn);
+        assertTrue(noInitialCrset.absolute(3));
+        assertEquals("update3", noInitialCrset.getString(2));
+        assertFalse(noInitialCrset.columnUpdated(2));
+
+        assertTrue(noInitialCrset.absolute(4));
+        try {
+            noInitialCrset.columnUpdated(0);
+            fail("should throw exception");
+        } catch (IndexOutOfBoundsException e) {
+            // RI throw IndexOutOfBoundsException
+        } catch (SQLException e) {
+            // expected
+        }
+
+        try {
+            noInitialCrset.columnUpdated("abc");
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+    }
+
+    public void testRowUpdated() throws Exception {
+        noInitialCrset = newNoInitialInstance();
+        try {
+            noInitialCrset.rowUpdated();
+            fail("should throw exception");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // RI throw exception here
+        } catch (SQLException e) {
+            // expected
+        }
+
+        rs = st.executeQuery("SELECT * FROM USER_INFO");
+        noInitialCrset.populate(rs);
+
+        assertTrue(noInitialCrset.isBeforeFirst());
+        try {
+            noInitialCrset.rowUpdated();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.afterLast();
+        assertTrue(noInitialCrset.isAfterLast());
+        try {
+            noInitialCrset.rowUpdated();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        assertTrue(noInitialCrset.absolute(3));
+        assertFalse(noInitialCrset.rowUpdated());
+        noInitialCrset.updateString(2, "update3");
+        assertFalse(noInitialCrset.rowUpdated());
+        noInitialCrset.updateRow();
+        assertTrue(noInitialCrset.rowUpdated());
+        noInitialCrset.acceptChanges(conn);
+        assertTrue(noInitialCrset.absolute(3));
+        assertEquals("update3", noInitialCrset.getString(2));
+        assertFalse(noInitialCrset.rowUpdated());
+
+        noInitialCrset.moveToInsertRow();
+        try {
+            noInitialCrset.rowUpdated();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.moveToCurrentRow();
+        assertTrue(noInitialCrset.absolute(4));
+        assertFalse(noInitialCrset.rowUpdated());
+        noInitialCrset.updateRow();
+        assertFalse(noInitialCrset.rowUpdated());
+        noInitialCrset.updateString(2, "abc");
+        noInitialCrset.updateRow();
+        assertTrue(noInitialCrset.rowUpdated());
+    }
+
+    public void testCancelRowUpdates() throws Exception {
+        noInitialCrset = newNoInitialInstance();
+        try {
+            noInitialCrset.cancelRowUpdates();
+            fail("should throw exception");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // RI throw exception here
+        } catch (SQLException e) {
+            // expected
+        }
+
+        rs = st.executeQuery("SELECT * FROM USER_INFO");
+        noInitialCrset.populate(rs);
+
+        assertTrue(noInitialCrset.isBeforeFirst());
+        try {
+            noInitialCrset.cancelRowUpdates();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.afterLast();
+        assertTrue(noInitialCrset.isAfterLast());
+        try {
+            noInitialCrset.cancelRowUpdates();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.moveToInsertRow();
+        try {
+            noInitialCrset.cancelRowUpdates();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.moveToCurrentRow();
+        assertTrue(noInitialCrset.absolute(2));
+        // no effect here
+        noInitialCrset.cancelRowUpdates();
+
+        assertTrue(noInitialCrset.absolute(3));
+        noInitialCrset.updateString(2, "update3");
+        // call cancelRowUpdates() before updateRow(), no effect here
+        noInitialCrset.cancelRowUpdates();
+        assertEquals("update3", noInitialCrset.getString(2));
+        noInitialCrset.updateRow();
+        noInitialCrset.acceptChanges(conn);
+        assertEquals("update3", noInitialCrset.getString(2));
+
+        assertTrue(noInitialCrset.absolute(4));
+        noInitialCrset.updateString(2, "update4");
+        assertEquals("update4", noInitialCrset.getString(2));
+        noInitialCrset.updateRow();
+        assertEquals("update4", noInitialCrset.getString(2));
+        // call cancelRowUpdates() after updateRow(), it works here
+        noInitialCrset.cancelRowUpdates();
+        assertEquals("test4", noInitialCrset.getString(2));
+        noInitialCrset.acceptChanges(conn);
+        assertEquals("test4", noInitialCrset.getString(2));
+    }
+
+    public void testUndoUpdate() throws Exception {
+        noInitialCrset = newNoInitialInstance();
+        try {
+            noInitialCrset.undoUpdate();
+            fail("should throw exception");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // RI throw exception here
+        } catch (SQLException e) {
+            // expected
+        }
+
+        rs = st.executeQuery("SELECT * FROM USER_INFO");
+        noInitialCrset.populate(rs);
+
+        assertTrue(noInitialCrset.isBeforeFirst());
+        try {
+            noInitialCrset.undoUpdate();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        noInitialCrset.afterLast();
+        assertTrue(noInitialCrset.isAfterLast());
+        try {
+            noInitialCrset.undoUpdate();
+            fail("should throw SQLException");
+        } catch (SQLException e) {
+            // expected
+        }
+
+        /*
+         * The implementation of RI's undoUpdate seems not follow the spec at
+         * all.
+         */
+        if ("true".equals(System.getProperty("Testing Harmony"))) {
+            assertTrue(noInitialCrset.absolute(3));
+            noInitialCrset.undoUpdate(); // no effect here
+
+            noInitialCrset.updateString(2, "update3");
+            noInitialCrset.undoUpdate(); // no effect here
+            assertEquals("update3", noInitialCrset.getString(2));
+            noInitialCrset.updateRow();
+            noInitialCrset.undoUpdate(); // effect here
+            assertEquals("test3", noInitialCrset.getString(2));
+
+            noInitialCrset.acceptChanges(conn);
+            assertEquals("test3", noInitialCrset.getString(2));
+            noInitialCrset.undoUpdate(); // no effect here
+
+            noInitialCrset.moveToInsertRow();
+            noInitialCrset.updateInt(1, 10);
+            noInitialCrset.updateString(2, "update10");
+            // undoUpdate() will set all columns of insert row null
+            noInitialCrset.undoUpdate();
+            for (int i = 1; i <= DEFAULT_COLUMN_COUNT; i++) {
+                assertNull(noInitialCrset.getObject(i));
+            }
+        } else {
+            assertTrue(noInitialCrset.absolute(3));
+            try {
+                noInitialCrset.undoUpdate();
+                fail("should throw SQLException");
+            } catch (SQLException e) {
+                // RI throw SQLException here.
+            }
+
+            noInitialCrset.updateString(2, "update3");
+            noInitialCrset.updateLong(3, 3333333L);
+            noInitialCrset.updateFloat(7, 3.3F);
+            try {
+                noInitialCrset.undoUpdate();
+                fail("should throw SQLException");
+            } catch (SQLException e) {
+                // RI throw SQLException here.
+            }
+
+            noInitialCrset.updateRow();
+            try {
+                noInitialCrset.undoUpdate();
+                fail("should throw SQLException");
+            } catch (SQLException e) {
+                // RI throw SQLException here.
+            }
+
+            noInitialCrset.acceptChanges(conn);
+            assertEquals("update3", noInitialCrset.getString(2));
+            assertEquals(3333333L, noInitialCrset.getLong(3));
+            assertEquals(3.3F, noInitialCrset.getFloat(7));
+            try {
+                noInitialCrset.undoUpdate();
+                fail("should throw SQLException");
+            } catch (SQLException e) {
+                // RI throw SQLException here.
+            }
+
+            noInitialCrset.moveToInsertRow();
+            noInitialCrset.updateInt(1, 10);
+            noInitialCrset.updateString(2, "update10");
+            noInitialCrset.insertRow();
+            try {
+                noInitialCrset.undoUpdate();
+                fail("should throw SQLException");
+            } catch (SQLException e) {
+                // RI throw SQLException here.
+            }
+            noInitialCrset.moveToCurrentRow();
+
+            noInitialCrset.absolute(4);
+            assertEquals(10, noInitialCrset.getInt(1));
+            noInitialCrset.updateString(2, "abc");
+            // undoUpdate() has no effect here
+            noInitialCrset.undoUpdate();
+            noInitialCrset.acceptChanges(conn);
+
+            // check db
+            rs = st.executeQuery("SELECT * FROM USER_INFO WHERE ID = 10");
+            assertTrue(rs.next());
+            assertEquals(10, rs.getInt(1));
+            assertEquals("abc", rs.getString(2));
+
+            noInitialCrset.absolute(4);
+            assertEquals(10, noInitialCrset.getInt(1));
+            try {
+                noInitialCrset.undoUpdate();
+                fail("should throw SQLException");
+            } catch (SQLException e) {
+                // RI throw SQLException here.
+            }
+        }
+    }
+
     public void testUpdateValue() throws Exception {
 
         try {

Modified: harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/SyncResolverTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/SyncResolverTest.java?rev=633371&r1=633370&r2=633371&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/SyncResolverTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/sql/src/test/java/org/apache/harmony/sql/tests/internal/rowset/SyncResolverTest.java Mon Mar  3 22:43:19 2008
@@ -20,13 +20,14 @@
 import java.sql.SQLException;
 
 import javax.sql.RowSetMetaData;
+import javax.sql.rowset.CachedRowSet;
 import javax.sql.rowset.RowSetMetaDataImpl;
+import javax.sql.rowset.spi.SyncProviderException;
 import javax.sql.rowset.spi.SyncResolver;
 
 import org.apache.harmony.sql.internal.rowset.CachedRow;
 import org.apache.harmony.sql.internal.rowset.SyncResolverImpl;
 
-
 public class SyncResolverTest extends CachedRowSetTestCase {
     @Override
     public void setUp() throws Exception {
@@ -39,41 +40,36 @@
     }
 
     public void testNotSupportMethods() throws Exception {
-        /*
-         * TODO uncomment below fragment code when Harmony support detect
-         * conflict, so the test can run on both RI and Harmony
-         */
-        // CachedRowSet copy = crset.createCopy();
-        //
-        // copy.absolute(3);
-        // crset.absolute(3);
-        //
-        // copy.updateString(2, "updated");
-        // assertEquals("updated", copy.getString(2));
-        // assertEquals("test3", crset.getString(2));
-        //
-        // copy.updateRow();
-        // copy.acceptChanges();
-        //
-        // assertEquals(copy.getString(2), "updated");
-        // assertEquals(crset.getString(2), "test3");
-        //
-        // crset.updateString(2, "again");
-        //
-        // assertEquals(copy.getString(2), "updated");
-        // assertEquals(crset.getString(2), "again");
-        //
-        // crset.updateRow();
-        //
-        // SyncProviderException ex = null;
-        // try {
-        // crset.acceptChanges(conn);
-        // } catch (SyncProviderException e) {
-        // ex = e;
-        // }
-        //
-        // SyncResolver resolver = ex.getSyncResolver();
-        SyncResolver resolver = new SyncResolverImpl(null);
+        CachedRowSet copy = crset.createCopy();
+
+        copy.absolute(3);
+        crset.absolute(3);
+
+        copy.updateString(2, "updated");
+        assertEquals("updated", copy.getString(2));
+        assertEquals("test3", crset.getString(2));
+
+        copy.updateRow();
+        copy.acceptChanges();
+
+        assertEquals(copy.getString(2), "updated");
+        assertEquals(crset.getString(2), "test3");
+
+        crset.updateString(2, "again");
+
+        assertEquals(copy.getString(2), "updated");
+        assertEquals(crset.getString(2), "again");
+
+        crset.updateRow();
+
+        SyncProviderException ex = null;
+        try {
+            crset.acceptChanges(conn);
+        } catch (SyncProviderException e) {
+            ex = e;
+        }
+
+        SyncResolver resolver = ex.getSyncResolver();
 
         try {
             resolver.absolute(1);
@@ -372,7 +368,7 @@
         resolver.addConflictRow(
                 new CachedRow(new Object[DEFAULT_COLUMN_COUNT]), 2,
                 SyncResolver.INSERT_ROW_CONFLICT);
-        
+
         try {
             resolver.getStatus();
             fail("Should throw NullPointerException");