db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ferna...@apache.org
Subject svn commit: r481252 [2/3] - in /db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests: master/ master/DerbyNet/ master/DerbyNetClient/ master/DerbyNetClient/jdk14/ master/j9_13/ master/j9_foundation/ master/jdk14/ suites/ tests/lang/
Date Fri, 01 Dec 2006 14:38:52 GMT
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UpdatableResultSetTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UpdatableResultSetTest.java?view=auto&rev=481252
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UpdatableResultSetTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UpdatableResultSetTest.java Fri Dec  1 06:38:49 2006
@@ -0,0 +1,4587 @@
+/*
+ 
+   Derby - Class 
+       org.apache.derbyTesting.functionTests.lang.UpdatableResultSetTest
+ 
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+ 
+      http://www.apache.org/licenses/LICENSE-2.0
+ 
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ 
+ */
+
+package org.apache.derbyTesting.functionTests.tests.lang;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+import org.apache.derbyTesting.functionTests.util.BigDecimalHandler;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+import junit.framework.*;
+import java.sql.*;
+
+
+/**
+ * This tests JDBC 2.0 updateable resultset - deleteRow, updateRow, and
+ * insertRow API
+ */
+public class UpdatableResultSetTest  extends BaseJDBCTestCase {
+    
+    private static boolean HAVE_BIG_DECIMAL;
+    
+    static {
+        if (BigDecimalHandler.representation != 
+                BigDecimalHandler.BIGDECIMAL_REPRESENTATION)
+        {
+            HAVE_BIG_DECIMAL = false;
+        } else {
+            HAVE_BIG_DECIMAL = true;
+        }
+    }
+    
+    private static String[] allUpdateXXXNames =
+    {
+        "updateShort",
+        "updateInt",
+        "updateLong",
+        "updateBigDecimal",
+        "updateFloat",
+        "updateDouble",
+        "updateString",
+        "updateAsciiStream",
+        "updateCharacterStream",
+        "updateByte",
+        "updateBytes",
+        "updateBinaryStream",
+        "updateClob",
+        "updateDate",
+        "updateTime",
+        "updateTimestamp",
+        "updateBlob",
+        "updateBoolean",
+        "updateNull",
+        "updateArray",
+        "updateRef"
+    };
+    
+    // test all the supported SQL datatypes using updateXXX methods
+    private static String[] allSQLTypes =
+    {
+        "SMALLINT",
+        "INTEGER",
+        "BIGINT",
+        "DECIMAL(10,5)",
+        "REAL",
+        "DOUBLE",
+        "CHAR(60)",
+        "VARCHAR(60)",
+        "LONG VARCHAR",
+        "CHAR(2) FOR BIT DATA",
+        "VARCHAR(2) FOR BIT DATA",
+        "LONG VARCHAR FOR BIT DATA",
+        "CLOB(1k)",
+        "DATE",
+        "TIME",
+        "TIMESTAMP",
+        "BLOB(1k)",
+    };
+    
+    // names for column names to test all the supported SQL datatypes using 
+    // updateXXX methods
+    private static String[] ColumnNames =
+    {
+        "SMALLINTCOL",
+        "INTEGERCOL",
+        "BIGINTCOL",
+        "DECIMALCOL",
+        "REALCOL",
+        "DOUBLECOL",
+        "CHARCOL",
+        "VARCHARCOL",
+        "LONGVARCHARCOL",
+        "CHARFORBITCOL",
+        "VARCHARFORBITCOL",
+        "LVARCHARFORBITCOL",
+        "CLOBCOL",
+        "DATECOL",
+        "TIMECOL",
+        "TIMESTAMPCOL",
+        "BLOBCOL",
+    };
+    
+    // data to test all the supported SQL datatypes using updateXXX methods
+    private static String[][]SQLData =
+    {
+        {"11","22"},                        // SMALLINT
+        {"111","1111"},                     // INTEGER
+        {"22","222"},                       // BIGINT
+        {"3.3","3.33"},                     // DECIMAL(10,5)
+        {"4.4","4.44"},                     // REAL,
+        {"5.5","5.55"},                     // DOUBLE
+        {"'1992-01-06'","'1992'"},          // CHAR(60)
+        {"'1992-01-07'","'1992'"},          // VARCHAR(60),
+        {"'1992-01-08'","'1992'"},          // LONG VARCHAR
+        {"X'10'","X'10aa'"},                // CHAR(2)  FOR BIT DATA
+        {"X'10'","X'10bb'"},                // VARCHAR(2) FOR BIT DATA
+        {"X'10'","X'10cc'"},                // LONG VARCHAR FOR BIT DATA
+        {"'13'","'14'"},                    // CLOB(1k)
+        {"'2000-01-01'","'2000-01-01'"},    // DATE
+        {"'15:30:20'","'15:30:20'"},        // TIME
+        {"'2000-01-01 15:30:20'","'2000-01-01 15:30:20'"}, // TIMESTAMP
+        {"X'1020'","X'10203040'"}           // BLOB
+    };
+    
+    // This table contains the expected result of the combination of datatype
+    // and updateXXX method on the embedded driver. If the call to the updateXXX
+    // method fails the cell contains the expected SQLState and if it passes the 
+    // cell contains PASS.
+    public static final String[][]  updateXXXRulesTableForEmbedded = {
+        
+        // Types.             u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u
+        //                    p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p
+        //                    d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d
+        //                    a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a
+        //                    t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t
+        //                    e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e
+        //                    S  I  L  B  F  D  S  A  C  B  B  B  C  D  T  T  B  B  N  A  R
+        //                    h  n  o  i  l  o  t  s  h  y  y  i  l  a  i  i  l  o  u  r  e
+        //                    o  t  n  g  o  u  r  c  a  t  t  n  o  t  m  m  o  o  l  r  f
+        //                    r     g  D  a  b  i  i  r  e  e  a  b  e  e  e  b  l  l  a
+        //                    t        e  t  l  n  i  c     s  r           s     e     y
+        //                             c     e  g  S  t        y           t     a
+        //                             i           t  e        S           a     n
+        //                             m           r  r        t           m
+        //                             a           e  S        r           p
+        //                             l           a  t        e
+        //                                         m  r        a
+        //                                            e        m
+        //                                            a
+        //                                            m
+        /* 0 SMALLINT      */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "XCL12", "22005", "22005", "XCL12", "XCL12", "XCL12", "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 1 INTEGER       */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "XCL12", "22005", "22005", "XCL12", "XCL12", "XCL12", "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 2 BIGINT        */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "XCL12", "22005", "22005", "XCL12", "XCL12", "XCL12", "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 3 DECIMAL       */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "XCL12", "22005", "22005", "XCL12", "XCL12", "XCL12", "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 4 REAL          */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "XCL12", "22005", "22005", "XCL12", "XCL12", "XCL12", "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 5 DOUBLE        */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "XCL12", "22005", "22005", "XCL12", "XCL12", "XCL12", "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 6 CHAR          */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "PASS",  "PASS",  "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 7 VARCHAR       */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "PASS",  "PASS",  "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 8 LONGVARCHAR   */  {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22005", "22005", "PASS",  "PASS",  "PASS",  "22005", "PASS",  "PASS", "0A000", "0A000"},
+        /* 9 CHAR FOR BIT  */  {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "22005", "22005", "XCL12", "PASS",  "PASS",  "22005", "XCL12", "XCL12", "XCL12", "22005", "XCL12", "PASS", "0A000", "0A000"},
+        /* 10 VARCH. BIT   */  {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "22005", "22005", "XCL12", "PASS",  "PASS",  "22005", "XCL12", "XCL12", "XCL12", "22005", "XCL12", "PASS", "0A000", "0A000"},
+        /* 11 LONGVAR. BIT */  {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "22005", "22005", "XCL12", "PASS",  "PASS",  "22005", "XCL12", "XCL12", "XCL12", "22005", "XCL12", "PASS", "0A000", "0A000"},
+        /* 12 CLOB         */  {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "22005", "PASS",  "XCL12", "XCL12", "XCL12", "22005", "XCL12", "PASS", "0A000", "0A000"},
+        /* 13 DATE         */  {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "22007", "22005", "22005", "XCL12", "XCL12", "22005", "22005", "PASS",  "XCL12", "PASS",  "22005", "XCL12", "PASS", "0A000", "0A000"},
+        /* 14 TIME         */  {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "22007", "22005", "22005", "XCL12", "XCL12", "22005", "22005", "XCL12", "PASS",  "PASS",  "22005", "XCL12", "PASS", "0A000", "0A000"},
+        /* 15 TIMESTAMP    */  {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "22007", "22005", "22005", "XCL12", "XCL12", "22005", "22005", "PASS",  "XCL12", "PASS",  "22005", "XCL12", "PASS", "0A000", "0A000"},
+        /* 16 BLOB         */  {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "22005", "22005", "XCL12", "PASS",  "PASS",  "22005", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "PASS", "0A000", "0A000"},
+    };
+    
+    // This table contains the expected result of the combination of datatype
+    // and updateXXX method on the network client driver. If the call to the 
+    // updateXXX method fails the cell contains the expected SQLState and if it
+    // passes the cell contains PASS.
+    public static final String[][]  updateXXXRulesTableForNetworkClient = {
+        
+        // Types.             u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u  u
+        //                    p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p  p
+        //                    d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d  d
+        //                    a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a  a
+        //                    t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t
+        //                    e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e
+        //                    S  I  L  B  F  D  S  A  C  B  B  B  C  D  T  T  B  B  N  A  R
+        //                    h  n  o  i  l  o  t  s  h  y  y  i  l  a  i  i  l  o  u  r  e
+        //                    o  t  n  g  o  u  r  c  a  t  t  n  o  t  m  m  o  o  l  r  f
+        //                    r     g  D  a  b  i  i  r  e  e  a  b  e  e  e  b  l  l  a
+        //                    t        e  t  l  n  i  c     s  r           s     e     y
+        //                             c     e  g  S  t        y           t     a
+        //                             i           t  e        S           a     n
+        //                             m           r  r        t           m
+        //                             a           e  S        r           p
+        //                             l           a  t        e
+        //                                         m  r        a
+        //                                            e        m
+        //                                            a
+        //                                            m
+        /* 0 SMALLINT      */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22018", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "0A000", "XCL12", "XCL12", "XCL12", "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 1 INTEGER       */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22018", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "0A000", "XCL12", "XCL12", "XCL12", "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 2 BIGINT        */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22018", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "0A000", "XCL12", "XCL12", "XCL12", "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 3 DECIMAL       */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22018", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "0A000", "XCL12", "XCL12", "XCL12", "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 4 REAL          */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "0A000", "XCL12", "XCL12", "XCL12", "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 5 DOUBLE        */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "0A000", "XCL12", "XCL12", "XCL12", "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 6 CHAR          */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "0A000", "PASS",  "PASS",  "PASS",  "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 7 VARCHAR       */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "0A000", "PASS",  "PASS",  "PASS",  "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 8 LONGVARCHAR   */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "0A000", "PASS",  "PASS",  "PASS",  "0A000", "PASS",  "PASS", "0A000", "0A000"},
+        /* 9 CHAR FOR BIT  */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "0A000", "XCL12", "XCL12", "XCL12", "0A000", "XCL12", "PASS", "0A000", "0A000"},
+        /* 10 VARCH. BIT   */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "0A000", "XCL12", "XCL12", "XCL12", "0A000", "XCL12", "PASS", "0A000", "0A000"},
+        /* 11 LONGVAR. BIT */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "0A000", "XCL12", "XCL12", "XCL12", "0A000", "XCL12", "PASS", "0A000", "0A000"},
+        /* 12 CLOB         */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "XCL12", "0A000", "XCL12", "XCL12", "XCL12", "0A000", "XCL12", "PASS", "0A000", "0A000"},
+        /* 13 DATE         */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "0A000", "PASS",  "XCL12", "PASS",  "0A000", "XCL12", "PASS", "0A000", "0A000"},
+        /* 14 TIME         */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "0A000", "XCL12", "PASS",  "PASS",  "0A000", "XCL12", "PASS", "0A000", "0A000"},
+        /* 15 TIMESTAMP    */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "0A000", "PASS",  "XCL12", "PASS",  "0A000", "XCL12", "PASS", "0A000", "0A000"},
+        /* 16 BLOB         */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "0A000", "XCL12", "XCL12", "XCL12", "0A000", "XCL12", "PASS", "0A000", "0A000"},
+    };
+    
+    // This table contains the expected result of the combination of datatype
+    // and updateObject method with a parameter of the type returned by the 
+    // getXXX method on the network client driver. If the call to the 
+    // updateObject method fails the cell contains the expected SQLState and if
+    // it passes the cell contains PASS.
+    public static final String[][]  updateObjectRulesTableForNetworkClient = {
+        
+        // Types.             g  g  g  g  g  g  g  g  g  g  g  g  g  g  g  g  g  g  g  g  g
+        //                    e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e  e
+        //                    t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t
+        //                    S  I  L  B  F  D  S  A  C  B  B  B  C  D  T  T  B  B  N  A  R
+        //                    h  n  o  i  l  o  t  s  h  y  y  i  l  a  i  i  l  o  u  r  e
+        //                    o  t  n  g  o  u  r  c  a  t  t  n  o  t  m  m  o  o  l  r  f
+        //                    r     g  D  a  b  i  i  r  e  e  a  b  e  e  e  b  l  l  a
+        //                    t        e  t  l  n  i  c     s  r           s     e     y
+        //                             c     e  g  S  t        y           t     a
+        //                             i           t  e        S           a     n
+        //                             m           r  r        t           m
+        //                             a           e  S        r           p
+        //                             l           a  t        e
+        //                                         m  r        a
+        //                                            e        m
+        //                                            a
+        //                                            m
+        /* 0 SMALLINT      */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22018", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 1 INTEGER       */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22018", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 2 BIGINT        */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22018", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 3 DECIMAL       */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "22018", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 4 REAL          */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 5 DOUBLE        */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 6 CHAR          */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 7 VARCHAR       */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 8 LONGVARCHAR   */ {"PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "PASS",  "PASS",  "PASS",  "PASS",  "XCL12", "PASS",  "PASS", "XCL12", "XCL12"},
+        /* 9 CHAR FOR BIT  */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "22001", "XCL12", "PASS", "XCL12", "XCL12"},
+        /* 10 VARCH. BIT   */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "22001", "XCL12", "PASS", "XCL12", "XCL12"},
+        /* 11 LONGVAR. BIT */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "PASS", "XCL12", "XCL12"},
+        /* 12 CLOB         */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "PASS",  "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS", "XCL12", "XCL12"},
+        /* 13 DATE         */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "PASS",  "XCL12", "XCL12", "PASS", "XCL12", "XCL12"},
+        /* 14 TIME         */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "XCL12", "XCL12", "PASS", "XCL12", "XCL12"},
+        /* 15 TIMESTAMP    */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "PASS",  "XCL12", "XCL12", "PASS", "XCL12", "XCL12"},
+        /* 16 BLOB         */ {"XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "PASS",  "XCL12", "XCL12", "XCL12", "XCL12", "PASS",  "XCL12", "PASS", "XCL12", "XCL12"},
+    };
+    
+    /**
+     * Creates a new instance of UpdatableResultSetTest
+     */
+    public UpdatableResultSetTest(String name) {
+        super(name);
+    }
+    
+    public static Test suite() {
+        TestSuite suite = new TestSuite("UpdatableResultSetTest");
+        
+        TestSuite embeddedSuite = baseSuite("UpdatableResultSetTest:embedded");
+        TestSuite clientSuite = baseSuite("UpdatableResultSetTest:client");
+        
+        if (JDBC.vmSupportsJDBC3()) {
+            embeddedSuite.addTest(
+                    new UpdatableResultSetTest("xTestInsertRowAfterCommit"));
+            clientSuite.addTest(
+                    new UpdatableResultSetTest("xTestInsertRowAfterCommit"));
+        }
+        
+        suite.addTest(new CleanDatabaseTestSetup(embeddedSuite));
+        suite.addTest(TestConfiguration.clientServerDecorator(
+                new CleanDatabaseTestSetup(clientSuite)));
+        
+        return suite;
+    }
+    
+    private static TestSuite baseSuite(String name) {
+        TestSuite suite = new TestSuite(name);
+        suite.addTestSuite(UpdatableResultSetTest.class);
+        return suite;
+    }
+    
+    protected void setUp() throws SQLException {
+        getConnection().setAutoCommit(false);
+    }
+    
+    /**
+     * Negative test - request for scroll sensitive updatable resultset will
+     * give an updatable scroll insensitive resultset
+     */
+    public void testScrollSensitiveResultSet() throws SQLException {
+        getConnection().clearWarnings();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
+        String sqlState = usingEmbedded() ? "01J02" : "01J10";
+        assertEquals("FAIL - Should get warning on Downgrade",
+                sqlState, getConnection().getWarnings().getSQLState());
+        assertEquals("FAIL - Result set type should be scroll insensitive",
+                ResultSet.TYPE_SCROLL_INSENSITIVE, stmt.getResultSetType());
+        assertEquals("FAIL - Result set concurrency should be updatable",
+                ResultSet.CONCUR_UPDATABLE, stmt.getResultSetConcurrency());
+    }
+    
+    /**
+     * Negative test - request a read only resultset and attempt deleteRow and
+     * updateRow on it
+     */
+    public void testUpdateDeleteRowOnReadOnlyResultSet() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement();
+        ResultSet rs = stmt.executeQuery("select * from t1");
+        assertEquals("FAIL - Result set concurrency should be read only",
+                ResultSet.CONCUR_READ_ONLY, rs.getConcurrency());
+        assertTrue("FAIL - row not found", rs.next());
+        
+        // attempt to send a deleteRow on a read only result set
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because this is a " +
+                    "read only resultset");
+        } catch (SQLException e) {
+            assertSQLState("XJ083", e);
+        }
+        
+        // attempt to send a updateRow on a read only result set
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed because this is a " +
+                    "read only resultset");
+        } catch (SQLException e) {
+            assertSQLState("XJ083", e);
+        }
+        rs.close();
+        
+        // verify that the data remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+        
+    }
+    
+    /**
+     * Negative Test - request a read only resultset and send a sql with FOR
+     * UPDATE clause and attempt deleteRow/updateRow on it
+     */
+    public void testUpdateDeleteRowOnReadOnlyResultSetWithForUpdate() 
+            throws SQLException 
+    {
+        createTableT1();
+        Statement stmt = createStatement();
+        ResultSet rs = stmt.executeQuery("select * from t1 FOR UPDATE");
+        assertEquals("FAIL - Result set concurrency should be read only",
+                ResultSet.CONCUR_READ_ONLY, rs.getConcurrency());
+        assertTrue("FAIL - row not found", rs.next());
+        
+        // attempt to send a deleteRow on a read only result set
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because this is a " +
+                    "read only resultset");
+        } catch (SQLException e) {
+            assertSQLState("XJ083", e);
+        }
+        
+        // attempt to send a updateRow on a read only result set
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed because this is a " +
+                    "read only resultset");
+        } catch (SQLException e) {
+            assertSQLState("XJ083", e);
+        }
+        rs.close();
+        
+        // verify that the data remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+    }
+    
+    
+    /**
+     * Negative Test - request resultset with no FOR UPDATE clause and 
+     * CONCUR_READ_ONLY
+     */
+    public void testUpdateDeleteRowOnReadOnlyResultSetWithoutForUpdate() 
+            throws SQLException 
+    {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+        ResultSet rs = stmt.executeQuery("select * from t1");
+        assertEquals("FAIL - Result set concurrency should be read only",
+                ResultSet.CONCUR_READ_ONLY, rs.getConcurrency());
+        assertTrue("FAIL - row not found", rs.next());
+        
+        // attempt to send a deleteRow on a read only result set
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because this is a " +
+                    "read only resultset");
+        } catch (SQLException e) {
+            assertSQLState("XJ083", e);
+        }
+        
+        // attempt to send a deleteRow on a read only result set
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed because this is a " +
+                    "read only resultset");
+        } catch (SQLException e) {
+            assertSQLState("XJ083", e);
+        }
+        rs.close();
+        
+        // verify that the data remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Negative Test - request updatable resultset for sql with FOR READ ONLY 
+     * clause
+     */
+    public void testUpdateDeleteRowOnUpdatableResultSetWithForReadOnly() 
+            throws SQLException 
+    {
+        createTableT1();
+        getConnection().clearWarnings();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("select * from t1 FOR READ ONLY");
+        assertEquals("FAIL - Result set concurrency should be read only",
+                ResultSet.CONCUR_READ_ONLY, rs.getConcurrency());
+        assertEquals("FAIL - FAIL - Should get warning on Downgrade",
+                "01J06", rs.getWarnings().getSQLState());
+        assertTrue("FAIL - row not found", rs.next());
+        
+        // Attempt to send a deleteRow on a read only result set"
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because this is a " +
+                    "read only resultset");
+        } catch (SQLException e) {
+            assertSQLState("XJ083", e);
+        }
+        
+        // Attempt to send a updateRow on a read only result set
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed because this is a " +
+                    "read only resultset");
+        } catch (SQLException e) {
+            assertSQLState("XJ083", e);
+        }
+        rs.close();
+        
+        // verify that the data remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Negative test - attempt to deleteRow & updateRow on updatable resultset
+     * when the resultset is not positioned on a row
+     */
+    public void testUpdateDeleteRowNotOnRow() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1");
+        assertEquals("FAIL - Result set concurrency should be updatable",
+                ResultSet.CONCUR_UPDATABLE, rs.getConcurrency());
+        
+        // Attempt to send a deleteRow without being positioned on a row
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed, not on a row");
+        } catch (SQLException e) {
+            assertSQLState("24000", e);
+        }
+        
+        // Attempt to send a deleteRow without being positioned on a row
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed, not on a row");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        //read all the rows from the resultset and position after the last row
+        while (rs.next());
+        
+        // attempt to send a deleteRow when positioned after the last row
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed, positioned " +
+                    "after last row");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XCL07";
+            assertSQLState(sqlState, e);
+        }
+        
+        // attempt to send a updateRow when positioned after the last row
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed, positioned " +
+                    "after last row");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        rs.close();
+        
+        // verify that the data remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Negative test - attempt deleteRow & updateRow on updatable resultset 
+     * after closing the resultset
+     */
+    public void testUpdateDeleteRowOnClosedResultSet() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1 FOR UPDATE");
+        assertEquals("FAIL - Result set concurrency should be updatable",
+                ResultSet.CONCUR_UPDATABLE, rs.getConcurrency());
+        assertTrue("FAIL - row not found", rs.next());
+        rs.close();
+        
+        // attempt to send a deleteRow on a closed result set
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because this " +
+                    "result set is closed");
+        } catch (SQLException e) {
+            assertSQLState("XCL16", e);
+        }
+        
+        // attempt to send a deleteRow on a closed result set
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed because this " +
+                    "result set is closed");
+        } catch (SQLException e) {
+            assertSQLState("XCL16", e);
+        }
+        rs.close();
+        
+        // verify that the data remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Negative test - try updatable resultset on system table
+     */
+    public void testUpdatableResultSetOnSysTable() throws SQLException {
+        try {
+            ResultSet rs = createStatement().
+                    executeQuery("SELECT * FROM sys.systables FOR UPDATE");
+            fail("FAIL - trying to open an updatable resultset on a system " +
+                    "table should have failed because system tables can't " +
+                    "be updated by a user");
+        } catch (SQLException e) {
+            assertSQLState("42Y90", e);
+        }
+    }
+    
+    /**
+     * Negative test - try updatable resultset on a view
+     */
+    public void testUpdatableResultSetOnView() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement();
+        stmt.executeUpdate("create view v1 as select * from t1");
+        try {
+            ResultSet rs = stmt.executeQuery("SELECT * FROM v1 FOR UPDATE");
+            fail("FAIL - trying to open an updatable resultset on a view " +
+                    "should have failed because Derby does not support " +
+                    "updates to views yet");
+        } catch (SQLException e) {
+            assertSQLState("42Y90", e);
+        }
+        stmt.executeUpdate("drop view v1");
+        stmt.close();
+    }
+    
+    /**
+     * Negative test - attempt to open updatable resultset when there is
+     * join in the select query should fail
+     */
+    public void testUpdatableResultSetOnJoin() throws SQLException {
+        createTableT1();
+        createTableT2();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        try {
+            ResultSet rs = stmt.executeQuery(
+                    "SELECT c1 FROM t1,t2 where t1.c1 = t2.c21 FOR UPDATE");
+            fail("FAIL - trying to open an updatable resultset should have " +
+                    "failed because updatable resultset donot support join " +
+                    "in the select query");
+        } catch (SQLException e) {
+            assertSQLState("42Y90", e);
+        }
+    }
+    
+    /**
+     * Negative test - With autocommit on, attempt to drop a table when there
+     * is an open updatable resultset on it
+     */
+    public void testDropTableWithUpatableResultSet() throws SQLException {
+        getConnection().setAutoCommit(true);
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("SELECT c1 FROM t1 FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        rs.updateInt(1,123);
+        
+        Statement stmt1 = createStatement();
+        try {
+            stmt1.executeUpdate("drop table t1");
+            fail("FAIL - drop table should have failed because the " +
+                    "updatable resultset is still open");
+        } catch (SQLException e) {
+            assertSQLState("X0X95", e);
+        }
+        stmt1.close();
+        
+        // Since autocommit is on, the drop table exception resulted in a
+        //runtime rollback causing updatable resultset object to close
+        try {
+            rs.updateRow();
+            fail("FAIL - resultset should have been closed at this point and " +
+                    "updateRow should have failed");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded()? "XCL16" : "24000";
+            assertSQLState(sqlState, e);
+        }
+        
+        try {
+            rs.deleteRow();
+            fail("FAIL - resultset should have been closed at this point and " +
+                    "deleteRow should have failed");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded()? "XCL16" : "24000";
+            assertSQLState(sqlState, e);
+        }
+        
+        // verify that the data remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.executeUpdate("DROP TABLE T1");
+        stmt.close();
+        
+    }
+    
+    /**
+     * Negative test - foreign key constraint failure will cause deleteRow
+     * to fail
+     */
+    public void testForeignKeyConstraintFailureOnDeleteRow() 
+            throws SQLException 
+    {
+        getConnection().setAutoCommit(true);
+        createTableWithPrimaryKey();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery(
+                "SELECT * FROM tableWithPrimaryKey FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because it will cause " +
+                    "foreign key constraint failure");
+        } catch (SQLException e) {
+            assertSQLState("23503", e);
+        }
+        // Since autocommit is on, the constraint exception resulted in a
+        // runtime rollback causing updatable resultset object to close
+        try {
+            rs.next();
+            // DERBY-160
+            if (usingEmbedded())
+                fail("FAIL - next should have failed because foreign key " +
+                        "constraint failure resulted in a runtime rollback");
+        } catch (SQLException e) {
+            assertFalse("FAIL - Network client should not fail due to " +
+                    "DERBY-160", !usingEmbedded());
+            assertSQLState("XCL16", e);
+        }
+        
+        // verify that the data is unchanged
+        String[][] expected = {{"1", "1"}, {"2", "2"}, {"3", "3"}, {"4", "4"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM tableWithPrimaryKey"),
+                expected, true);
+        stmt.executeUpdate("DROP TABLE tableWithConstraint");
+        stmt.executeUpdate("DROP TABLE tableWithPrimaryKey");
+        stmt.close();
+    }
+    
+    /**
+     * Negative test - foreign key constraint failure will cause updateRow
+     * to fail
+     */
+    public void testForeignKeyConstraintFailureOnUpdateRow() 
+            throws SQLException 
+    {
+        getConnection().setAutoCommit(true);
+        createTableWithPrimaryKey();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery(
+                "SELECT c1, c2 FROM tableWithPrimaryKey FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        rs.updateInt(1,11);
+        rs.updateInt(2,22);
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed because it will cause " +
+                    "foreign key constraint failure");
+        } catch (SQLException e) {
+            assertSQLState("23503", e);
+        }
+        // Since autocommit is on, the constraint exception resulted in a
+        // runtime rollback causing updatable resultset object to close
+        try {
+            rs.next();
+            // DERBY-160
+            if (usingEmbedded())
+                fail("FAIL - next should have failed because foreign key " +
+                        "constraint failure resulted in a runtime rollback");
+        } catch (SQLException e) {
+            assertFalse("FAIL - Network client should not fail due to " +
+                    "DERBY-160", !usingEmbedded());
+            assertSQLState("XCL16", e);
+        }
+        
+        // verify that the data is unchanged
+        String[][] expected = {{"1", "1"}, {"2", "2"}, {"3", "3"}, {"4", "4"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM tableWithPrimaryKey"),
+                expected, true);
+        stmt.executeUpdate("DROP TABLE tableWithConstraint");
+        stmt.executeUpdate("DROP TABLE tableWithPrimaryKey");
+        stmt.close();
+    }
+    
+    /**
+     * Negative test - Can't call updateXXX methods on columns that do not
+     * correspond to a column in the table
+     */
+    public void testUpdateXXXOnColumnNotFromTable() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("SELECT 1, 2 FROM t1 FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        try {
+            rs.updateInt(1,22);
+            fail("FAIL - updateInt should have failed because it is trying " +
+                    "to update a column that does not correspond to column " +
+                    "in base table");
+        } catch (SQLException e) {
+            String sqlState = (usingEmbedded()) ? "XJ084" : "XJ124";
+            assertSQLState(sqlState, e);
+        }
+        rs.close();
+        stmt.close();
+    }
+    
+    /**
+     * Negative test - Call updateXXX method on out of the range column
+     */
+    public void testUpdateXXXOnOutOfRangeColumn() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("SELECT c1, c2 FROM t1 FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        try {
+            println("There are only 2 columns in the select list and we are " +
+                    "trying to send updateXXX on column position 3");
+            rs.updateInt(3,22);
+            fail("FAIL - updateInt should have failed because there are " +
+                    "only 2 columns in the select list");
+        } catch (SQLException e) {
+            assertSQLState("XCL14", e);
+        }
+        rs.close();
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - request updatable resultset for forward only type 
+     * resultset
+     */
+    public void testResultSetNotPositionedAfterDeleteRow() 
+            throws SQLException 
+    {
+        createTableT1();
+        getConnection().clearWarnings();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        assertNull("FAIL - should not get a warning",
+                getConnection().getWarnings());
+        assertEquals("FAIL - wrong result set type",
+                ResultSet.TYPE_FORWARD_ONLY, stmt.getResultSetType());
+        assertEquals("FAIL - wrong result set concurrency",
+                ResultSet.CONCUR_UPDATABLE, stmt.getResultSetConcurrency());
+        
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1");
+        assertTrue("FAIL - row not found", rs.next());
+        int c1Before = rs.getInt(1);
+        String c2Before = rs.getString(2);
+        rs.deleteRow();
+        // Calling getXXX will fail because the result set is positioned before
+        //the next row.
+        try {
+            rs.getInt(1);
+            fail("FAIL - result set not positioned on a row, rs.getInt(1) " +
+                    "should have failed");
+        } catch (SQLException e) {
+            String sqlState = (usingEmbedded()) ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // Calling deleteRow again again w/o first positioning the ResultSet on
+        // the next row will fail
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because ResultSet is " +
+                    "not positioned on a row");
+        } catch (SQLException e) {
+            assertSQLState("24000", e);
+        }
+        
+        // position the result set on the next row
+        assertTrue("FAIL - row not found", rs.next());
+        // calling delete row not will not fail because the result set is
+        // positioned
+        rs.deleteRow();
+        rs.close();
+        
+        // verify that the table contains one row
+        String[][] expected = {{"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - request updatable resultset for forward only type
+     * resultset
+     */
+    public void testResultSetNotPositionedAfterUpdateRow() 
+            throws SQLException 
+    {
+        createTableT1();
+        getConnection().clearWarnings();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        assertNull("FAIL - should not get a warning",
+                getConnection().getWarnings());
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1 FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        
+        int c1Before = rs.getInt(1);
+        rs.updateInt(1,234);
+        assertEquals("FAIL - column should have updated value",
+                234, rs.getInt(1));
+        assertEquals("FAIL - value of column 2 should not have changed",
+                "aa", rs.getString(2).trim());
+        println("now updateRow on the row");
+        rs.updateRow();
+        // Calling getXXX method will fail because after updateRow the result
+        // set is positioned before the next row
+        try {
+            rs.getInt(1);
+            fail("FAIL - result set not positioned on a row, rs.getInt(1) " +
+                    "should have failed");
+        } catch (SQLException e) {
+            String sqlState = (usingEmbedded()) ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // calling updateRow again w/o first positioning the ResultSet on the
+        // next row will fail
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed because ResultSet is " +
+                    "not positioned on a row");
+        } catch (SQLException e) {
+            String sqlState = (usingEmbedded()) ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // Position the ResultSet with next()
+        assertTrue("FAIL - row not found", rs.next());
+        //Should be able to updateRow() on the current row now
+        rs.updateString(2,"234");
+        rs.updateRow();
+        rs.close();
+        
+        // Verify that the data was correctly updated
+        String[][] expected = {{"234", "aa"}, {"2", "234"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - use updatable resultset to do postitioned delete
+     */
+    public void testPositionedDeleteOnUpdatableResultSet() 
+            throws SQLException 
+    {
+        createTableT1();
+        getConnection().clearWarnings();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        assertNull("FAIL - should not get a warning",
+                getConnection().getWarnings());
+        assertEquals("FAIL - wrong result set type",
+                ResultSet.TYPE_FORWARD_ONLY, stmt.getResultSetType());
+        assertEquals("FAIL - wrong result set concurrency",
+                ResultSet.CONCUR_UPDATABLE, stmt.getResultSetConcurrency());
+        
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1");
+        assertTrue("FAIL - row not found", rs.next());
+        int c1Before = rs.getInt(1);
+        String c2Before = rs.getString(2);
+        PreparedStatement pStmt = prepareStatement(
+                "DELETE FROM T1 WHERE CURRENT OF " + rs.getCursorName());
+        pStmt.executeUpdate();
+        assertEquals("FAIL - wrong value on deleted row",
+                c1Before, rs.getInt(1));
+        assertEquals("FAIL - wrong value on deleted row",
+                c2Before, rs.getString(2));
+        
+        // doing positioned delete again w/o first positioning the ResultSet on
+        // the next row will fail
+        try {
+            pStmt.executeUpdate();
+            fail("FAIL - positioned delete should have failed because " +
+                    "ResultSet is not positioned on a row");
+        } catch (SQLException e) {
+            assertSQLState("24000", e);
+        }
+        
+        // Position the ResultSet with next()
+        assertTrue("FAIL - row not found", rs.next());
+        //Should be able to do positioned delete on the current row now
+        pStmt.executeUpdate();
+        
+        rs.close();
+        pStmt.close();
+        
+        
+        // Verify that the data was correctly updated
+        String[][] expected = {{"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - updatable resultset to do positioned update
+     */
+    public void testPositionedUpdateOnUpdatableResultSet() 
+            throws SQLException 
+    {
+        createTableT1();
+        getConnection().clearWarnings();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        assertNull("FAIL - should not get a warning",
+                getConnection().getWarnings());
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1");
+        assertTrue("FAIL - row not found", rs.next());
+        
+        int c1Before = rs.getInt(1);
+        String c2Before = rs.getString(2);
+        PreparedStatement pStmt = prepareStatement(
+                "UPDATE T1 SET C1=?, C2=? WHERE CURRENT OF " +
+                rs.getCursorName());
+        final int c1 = 2345;
+        final String c2 = "UUU";
+        pStmt.setInt(1, c1);
+        pStmt.setString(2, c2); // current value
+        pStmt.executeUpdate();
+        
+        assertEquals("FAIL - column 1 should have the original value",
+                c1Before, rs.getInt(1));
+        assertEquals("FAIL - column 2 should have the original value",
+                c2Before, rs.getString(2));
+        
+        // refreshRow will fail, not implemented for this type of result set
+        try {
+            rs.refreshRow();
+            fail("FAIL - refreshRow not implemented for this type of " +
+                    "result set");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "0A000" : "XJ125";
+            assertSQLState(sqlState, e);
+        }
+        
+        // a sencond positioned update will succed because the cursor is still
+        // positioned
+        pStmt.setInt(1, c1);
+        pStmt.setString(2, c2); // current value
+        pStmt.executeUpdate();
+        
+        // Position the ResultSet with next()
+        assertTrue("FAIL - row not found", rs.next());
+        // Should still be able to do positioned update
+        pStmt.setInt(1, rs.getInt(1)); // current value
+        pStmt.setString(2, "abc");
+        pStmt.executeUpdate();
+        
+        rs.close();
+        
+        // Verify that the data was correctly updated
+        String[][] expected = {{"2345", "UUU"}, {"2", "abc"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                stmt.executeQuery("SELECT * FROM t1"), expected, true);
+        stmt.close();
+        pStmt.close();
+    }
+    
+    /**
+     * Positive Test2 - even if no columns from table specified in the column
+     * list, we should be able to get updatable resultset
+     */
+    public void testUpdatableResultsetNoColumnInColumnList() 
+            throws SQLException 
+    {
+        // Will work in embedded mode because target table is not derived from
+        // the columns in the select list
+        // Will not work in network server mode because it derives the target
+        // table from the columns in the select list");
+        getConnection().setAutoCommit(true);
+        createTableT1();
+        
+        // Get row count
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("select count(*) from t1");
+        assertTrue("FAIL - statement should return a row", rs.next());
+        int origCount = rs.getInt(1);
+        assertEquals("FAIL - wrong row count", 3, origCount);
+        
+        rs = stmt.executeQuery("SELECT 1, 2 FROM t1 FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column 1", 1, rs.getInt(1));
+        try {
+            rs.deleteRow();
+            assertTrue("FAIL - should have failed in network server",
+                    usingEmbedded());
+        } catch (SQLException e) {
+            assertTrue("FAIL - should not fail on embedded", !usingEmbedded());
+            assertSQLState("42X01", e);
+        }
+        rs.close();
+        
+        rs = stmt.executeQuery("select count(*) from t1");
+        assertTrue("FAIL - statement should return a row", rs.next());
+        int count = rs.getInt(1);
+        if (usingEmbedded()) {
+            assertEquals("FAIL - wrong row count", (origCount - 1), count);
+        } else {
+            assertEquals("FAIL - wrong row count", (origCount), count);
+        }
+        rs.close();
+        stmt.execute("DROP TABLE T1");
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - use prepared statement with concur updatable status to
+     * test deleteRow
+     */
+    public void testDeleteRowWithPreparedStatement() throws SQLException {
+        createTableT1();
+        PreparedStatement pStmt = getConnection().prepareStatement(
+                "select * from t1 where c1 > ?",
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        assertEquals("FAIL - wrong result set type",
+                ResultSet.TYPE_FORWARD_ONLY, pStmt.getResultSetType());
+        assertEquals("FAIL - wrong result set concurrency",
+                ResultSet.CONCUR_UPDATABLE, pStmt.getResultSetConcurrency());
+        pStmt.setInt(1,0);
+        ResultSet rs = pStmt.executeQuery();
+        assertTrue("FAIL - statement should return a row", rs.next());
+        int c1Before = rs.getInt(1);
+        rs.deleteRow();
+        
+        // Since after deleteRow(), ResultSet is positioned before the next
+        // row, getXXX will fail
+        try {
+            rs.getInt(1);
+            fail("FAIL - not on a row, can not get column");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // calling deleteRow again w/o first positioning the ResultSet on the
+        // next row will fail
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because it can't be " +
+                    "called more than once on the same row");
+        } catch (SQLException e) {
+            String sqlState = "24000";
+            assertSQLState(sqlState, e);
+        }
+        
+        // Position the ResultSet with next()
+        assertTrue("FAIL - statement should return a row", rs.next());
+        //Derby-718 check that column values are not null after next()
+        assertFalse("FAIL - first column should not be 0", rs.getInt(1) == 0);
+        // Derby-718
+        // Should be able to deletRow() on the current row now
+        rs.deleteRow();
+        
+        rs.close();
+        pStmt.close();
+        
+        // Verify that the data was correctly updated
+        String[][] expected = {{"3", "cc"}};
+        JDBC.assertFullResultSet(
+                createStatement().executeQuery("SELECT * FROM t1"),
+                expected, true);
+    }
+    
+    /**
+     * Positive test - use prepared statement with concur updatable status to
+     * test updateXXX
+     */
+    public void testUpdateXXXWithPreparedStatement() throws SQLException {
+        createTableT1();
+        PreparedStatement pStmt = getConnection().prepareStatement(
+                "select * from t1 where c1>? for update",
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        assertEquals("FAIL - wrong result set type",
+                ResultSet.TYPE_FORWARD_ONLY, pStmt.getResultSetType());
+        assertEquals("FAIL - wrong result set concurrency",
+                ResultSet.CONCUR_UPDATABLE, pStmt.getResultSetConcurrency());
+        pStmt.setInt(1,0);
+        ResultSet rs = pStmt.executeQuery();
+        
+        assertTrue("FAIL - statement should return a row", rs.next());
+        assertEquals("FAIL - wrong value for column 1", 1, rs.getInt(1));
+        rs.updateInt(1,5);
+        assertEquals("FAIL - wrong value for column 5", 5, rs.getInt(1));
+        rs.updateRow();
+        
+        // Since after updateRow(), ResultSet is positioned before the next row,
+        // getXXX will fail
+        try {
+            rs.getInt(1);
+            fail("FAIL - not on a row, can not get column");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // calling updateXXX again w/o first positioning the ResultSet on the
+        //next row will fail
+        try {
+            rs.updateInt(1,0);
+            fail("FAIL - updateXXX should have failed because resultset is " +
+                    "not positioned on a row");
+        }catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // calling updateRow again w/o first positioning the ResultSet on the
+        // next row will fail
+        try {
+            rs.updateRow();
+            fail("FAIL - updateRow should have failed because resultset is " +
+                    "not positioned on a row");
+        }catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // calling cancelRowUpdates will fail because the result set is not
+        // positioned
+        try {
+            rs.cancelRowUpdates();
+            fail("FAIL - cancelRowUpdates should have failed because the " +
+                    "resultset is not positioned on a row");
+        }catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // Position the ResultSet with next()
+        assertTrue("FAIL - statement should return a row", rs.next());
+        // Should be able to cancelRowUpdates() on the current row now"
+        rs.cancelRowUpdates();
+        rs.close();
+        pStmt.close();
+        
+        // Verify that the data was correctly updated
+        String[][] expected = {{"5", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(
+                createStatement().executeQuery("SELECT * FROM t1"),
+                expected, true);
+    }
+    
+    /**
+     * Positive test - use callable statement with concur updatable status
+     */
+    public void testCallableStatementWithUpdatableResultSet() 
+            throws SQLException 
+    {
+        createTableT1();
+        CallableStatement callStmt = getConnection().prepareCall(
+                "select * from t1",
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = callStmt.executeQuery();
+        assertEquals("FAIL - wrong result set type",
+                ResultSet.TYPE_FORWARD_ONLY, callStmt.getResultSetType());
+        assertEquals("FAIL - wrong result set concurrency",
+                ResultSet.CONCUR_UPDATABLE, callStmt.getResultSetConcurrency());
+        assertTrue("FAIL - statement should return a row", rs.next());
+        assertEquals("FAIL - wrong value for column 1", 1, rs.getInt(1));
+        rs.deleteRow();
+        
+        // Since after deleteRow(), ResultSet is positioned before the next row,
+        // getXXX will fail
+        try {
+            rs.getInt(1);
+            fail("FAIL - not on row, can not get value");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XJ121";
+            assertSQLState(sqlState, e);
+        }
+        
+        // calling deleteRow again w/o first positioning the ResultSet on the
+        // next row will fail
+        try {
+            rs.deleteRow();
+            fail("FAIL - deleteRow should have failed because it can't be " +
+                    "called more than once on the same row");
+        } catch (SQLException e) {
+            String sqlState = "24000";
+            assertSQLState(sqlState, e);
+        }
+        
+        // Position the ResultSet with next()
+        assertTrue("FAIL - statement should return a row", rs.next());
+        // Should be able to deletRow() on the current row now
+        rs.deleteRow();
+        //have to close the resultset because by default, resultsets are held
+        // open over commit
+        rs.close();
+        callStmt.close();
+        
+        // Verify that the data was correctly updated
+        String[][] expected = {{"3", "cc"}};
+        JDBC.assertFullResultSet(
+                createStatement().executeQuery("SELECT * FROM t1"),
+                expected, true);
+    }
+    
+    /**
+     * Positive test - donot have to select primary key to get an updatable
+     * resultset
+     */
+    public void testUpdatableResultSetWithoutSelectingPrimaryKey()
+    throws SQLException {
+        createTableT3();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("SELECT c32 FROM t3");
+        assertTrue("FAIL - statement should return a row", rs.next());
+        assertEquals("FAIL - wrong value for column 1", 1, rs.getInt(1));
+        // now try to delete row when primary key is not selected for that row
+        rs.deleteRow();
+        assertTrue("FAIL - statement should return a row", rs.next());
+        rs.updateLong(1,123);
+        rs.updateRow();
+        rs.close();
+        
+        // verify that the table was correctly update
+        String[][] expected = {{"2", "123"}, {"3", "3"}, {"4", "4"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("select * from t3"),
+                expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - For Forward Only resultsets, DatabaseMetaData will
+     * return false for ownDeletesAreVisible and deletesAreDetected
+     * This is because, after deleteRow, we position the ResultSet before the
+     * next row. We don't make a hole for the deleted row and then stay on that
+     * deleted hole
+     */
+    public void testRowDeleted() throws SQLException {
+        DatabaseMetaData dbmt = getConnection().getMetaData();
+        assertEquals("FAIL - wrong values for ownDeletesAreVisible(" +
+                "ResultSet.TYPE_FORWARD_ONLY)", false,
+                dbmt.ownDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        assertEquals("FAIL - wrong values for othersDeletesAreVisible(" +
+                "ResultSet.TYPE_FORWARD_ONLY)", true,
+                dbmt.othersDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        assertEquals("FAIL - wrong value for deletesAreDetected(" +
+                "ResultSet.TYPE_FORWARD_ONLY)", false,
+                dbmt.deletesAreDetected(ResultSet.TYPE_FORWARD_ONLY));
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery(
+                "SELECT * FROM t1 FOR UPDATE of c1");
+        assertTrue("FAIL - statement should return a row", rs.next());
+        assertFalse("FAIL - rs.rowDeleted() should always return false for " +
+                "this type of result set", rs.rowDeleted());
+        rs.deleteRow();
+        rs.close();
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - For Forward Only resultsets, DatabaseMetaData will return
+     * false for ownUpdatesAreVisible and updatesAreDetected
+     * This is because, after updateRow, we position the ResultSet before the
+     * next row
+     */
+    public void testRowUpdated() throws SQLException {
+        DatabaseMetaData dbmt = getConnection().getMetaData();
+        assertEquals("FAIL - wrong values for ownUpdatesAreVisible(" +
+                "ResultSet.TYPE_FORWARD_ONLY)", false,
+                dbmt.ownUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        assertEquals("FAIL - wrong values for othersUpdatesAreVisible(" +
+                "ResultSet.TYPE_FORWARD_ONLY)", true,
+                dbmt.othersUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+        assertEquals("FAIL - wrong values for updatesAreDetected(" +
+                "ResultSet.TYPE_FORWARD_ONLY)", false,
+                dbmt.updatesAreDetected(ResultSet.TYPE_FORWARD_ONLY));
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1 FOR UPDATE of c1");
+        assertTrue("FAIL - statement should return a row", rs.next());
+        assertFalse("FAIL - rs.rowUpdated() should always return false for " +
+                "this type of result set", rs.rowUpdated());
+        rs.updateLong(1,123);
+        rs.updateRow();
+        rs.close();
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - delete using updatable resultset api from a temporary
+     * table
+     */
+    public void testDeleteRowOnTempTable() throws SQLException {
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        stmt.executeUpdate("DECLARE GLOBAL TEMPORARY TABLE " +
+                "SESSION.t2(c21 int, c22 int) " +
+                "on commit preserve rows not logged");
+        stmt.executeUpdate("insert into SESSION.t2 values(21, 1)");
+        stmt.executeUpdate("insert into SESSION.t2 values(22, 1)");
+        
+        println("following rows in temp table before deleteRow");
+        ResultSet rs = stmt.executeQuery("select * from SESSION.t2");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column c21", 21, rs.getInt(1));
+        assertEquals("FAIL - wrong value for column c21", 1, rs.getInt(2));
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column c21", 22, rs.getInt(1));
+        assertEquals("FAIL - wrong value for column c21", 1, rs.getInt(2));
+        rs.close();
+        
+        rs = stmt.executeQuery("select c21 from session.t2 for update");
+        assertTrue("FAIL - row not found", rs.next());
+        rs.deleteRow();
+        assertTrue("FAIL - row not found", rs.next());
+        assertFalse("FAIL - Column c21 should not be 0", rs.getInt(1) == 0);
+        rs.deleteRow();
+        println("As expected, no rows in temp table after deleteRow");
+        rs.close();
+        
+        rs = stmt.executeQuery("select * from SESSION.t2");
+        assertFalse("FAIL - all rows were deleted, rs.next() should " +
+                "return false", rs.next());
+        rs.close();
+        
+        stmt.executeUpdate("DROP TABLE SESSION.t2");
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - update using updatable resultset api from a temporary
+     * table
+     */
+    public void testUpdateRowOnTempTable() throws SQLException {
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        stmt.executeUpdate("DECLARE GLOBAL TEMPORARY TABLE " +
+                "SESSION.t3(c31 int, c32 int) " +
+                "on commit preserve rows not logged");
+        stmt.executeUpdate("insert into SESSION.t3 values(21, 1)");
+        stmt.executeUpdate("insert into SESSION.t3 values(22, 1)");
+        
+        println("following rows in temp table before deleteRow");
+        ResultSet rs = stmt.executeQuery("select * from SESSION.t3");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column c21", 21, rs.getInt(1));
+        assertEquals("FAIL - wrong value for column c21", 1, rs.getInt(2));
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column c21", 22, rs.getInt(1));
+        assertEquals("FAIL - wrong value for column c21", 1, rs.getInt(2));
+        rs.close();
+        
+        rs = stmt.executeQuery("select c31 from session.t3");
+        assertTrue("FAIL - row not found", rs.next());
+        rs.updateLong(1,123);
+        rs.updateRow();
+        assertTrue("FAIL - row not found", rs.next());
+        rs.updateLong(1,123);
+        rs.updateRow();
+        rs.close();
+        
+        int countRows = 0;
+        rs = stmt.executeQuery("select * from SESSION.t3");
+        while (rs.next()) {
+            countRows++;
+            assertEquals("FAIL - wrong value for column c21",
+                    123, rs.getInt(1));
+            assertEquals("FAIL - wrong value for column c21",
+                    1, rs.getInt(2));
+        }
+        assertEquals("FAIL - wrong row count", 2, countRows);
+        rs.close();
+        
+        stmt.executeUpdate("DROP TABLE SESSION.t3");
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - change the name of the statement when the resultset is
+     * open and see if deleteRow still works
+     * This test works in embedded mode since Derby can handle the change in the
+     * name of the statement with an open resultset
+     * But it fails under Network Server mode because JCC and Derby Net Client
+     * do not allow statement name change when there an open resultset against
+     * it
+     */
+    public void testDeleteRowWithSetCursorName() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        // change the cursor name(case sensitive name) with setCursorName and
+        // then try to deleteRow
+        stmt.setCursorName("CURSORNOUPDATe");
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1 FOR UPDATE of c1");
+        assertTrue("FAIL - row not found", rs.next());
+        rs.deleteRow();
+        // change the cursor name one more time with setCursorName and then try
+        // to deleteRow
+        try {
+            stmt.setCursorName("CURSORNOUPDATE1");
+            assertTrue("FAIL - expected exception in network client",
+                    usingEmbedded());
+        } catch (SQLException e) {
+            if (!usingEmbedded()) {
+                assertSQLState("X0X95", e);
+            } else {
+                // throw unexpected exception
+                throw e;
+            }            
+        }
+        assertTrue("FAIL - row not found", rs.next());
+        rs.deleteRow();
+        rs.close();
+        
+        // verify that the table was correctly update
+        String[][] expected = {{"3", "cc"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("SELECT * FROM t1"),
+                expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - change the name of the statement when the resultset is
+     * open and see if updateRow still works
+     * This test works in embedded mode since Derby can handle the change in the
+     * name of the statement with an open resultset
+     * But it fails under Network Server mode because JCC and Derby Net Client
+     * do not allow statement name change when there an open resultset against
+     * it
+     */
+    public void testUpdateRowWithSetCursorName() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        // change the cursor name(case sensitive name) with setCursorName and
+        // then try to updateRow
+        stmt.setCursorName("CURSORNOUPDATe");
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1 FOR UPDATE of c1");
+        assertTrue("FAIL - row not found", rs.next());
+        rs.updateLong(1, 123);
+        try {
+            stmt.setCursorName("CURSORNOUPDATE1");
+            assertTrue("FAIL - expected exception in network client",
+                    usingEmbedded());
+        } catch (SQLException e) {
+            if (!usingEmbedded()) {
+                assertSQLState("X0X95", e);
+            } else {
+                // throw unexpected exception
+                throw e;
+            }
+        }
+        rs.updateRow();
+        rs.close();
+        
+        // verify that the table was correctly update
+        String[][] expected = {{"123", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("SELECT * FROM t1"),
+                expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - using correlation name for the table in the select sql
+     */
+    public void testDeleteRowWithCorrelationForTableName() 
+            throws SQLException 
+    {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery(
+                "SELECT * FROM t1 abcde FOR UPDATE of c1");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column 1", 1, rs.getInt(1));
+        // now try to deleteRow
+        rs.deleteRow();
+        rs.close();
+        
+        // verify that the table was correctly update
+        String[][] expected = {{"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("SELECT * FROM t1"), 
+                expected, true);
+        stmt.close();
+    }
+    
+    
+    /**
+     * Positive Test9b - using correlation name for updatable columns is not
+     * allowed.
+     */
+    public void testDeleteRowWithCorrelationForColumnName() 
+            throws SQLException 
+    {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        // attempt to get an updatable resultset using correlation name for an
+        // updatable column
+        try {
+            ResultSet rs = stmt.executeQuery(
+                    "SELECT c1 as col1, c2 as col2 FROM t1 abcde " +
+                    "FOR UPDATE of c1");
+            fail("FAIL - executeQuery should have failed");
+        } catch (SQLException e) {
+            assertSQLState("42X42", e);
+        }
+        // attempt to get an updatable resultset using correlation name for an
+        // readonly column. It should work
+        ResultSet rs = stmt.executeQuery(
+                "SELECT c1, c2 as col2 FROM t1 abcde FOR UPDATE of c1");
+        assertTrue("FAIL - row not found", rs.next());
+        rs.updateInt(1,11);
+        rs.updateRow();
+        rs.close();
+        
+        // verify that the table was correctly update
+        String[][] expected = {{"11", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("SELECT * FROM t1"),
+                expected, true);
+        stmt.close();
+        
+    }
+    
+    /**
+     * Positive test - try to updateXXX on a readonly column. Should get error
+     */
+    public void testUpdateXXXOnReadOnlyColumn() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery(
+                "SELECT c1, c2 FROM t1 abcde FOR UPDATE of c1");
+        assertTrue("FAIL - row not found", rs.next());
+        // attempt to update a read only column
+        try {
+            rs.updateString(2,"bbbb");
+            fail("FAIL - updateString on readonly column should have failed");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "42X31" : "XJ124";
+            assertSQLState(sqlState, e);
+        }
+        rs.close();
+        
+        // verify that the table remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("SELECT * FROM t1"),
+                expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - try to get an updatable resultset using correlation name
+     * for a readonly column
+     */
+    public void testUpdateRowWithCorrelationOnTableAndColumn()
+    throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        // attempt to get an updatable resultset using correlation name for a
+        // readonly column. It should work
+        ResultSet rs = stmt.executeQuery(
+                "SELECT c1, c2 as col2 FROM t1 abcde FOR UPDATE of c1");
+        assertTrue("FAIL - row not found", rs.next());
+        rs.updateInt(1,11);
+        rs.updateRow();
+        rs.close();
+        
+        // verify that the table was correctly update
+        String[][] expected = {{"11", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("SELECT * FROM t1"),
+                expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - try to updateXXX on a readonly column with correlation
+     * name. Should get error
+     */
+    public void testUpdateXXXOnReadOnlyColumnWithCorrelationName()
+    throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery(
+                "SELECT c1, c2 as col2 FROM t1 abcde FOR UPDATE of c1");
+        assertTrue("FAIL - row not found", rs.next());
+        try {
+            rs.updateString(2,"bbbb");
+            fail("FAIL - updateString on readonly column should have failed");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "42X31" : "XJ124";
+            assertSQLState(sqlState, e);
+        }
+        rs.close();
+        
+        // verify that the table remains unchanged
+        String expected[][] = {{"1", "aa"}, {"2", "bb"}, {"3", "cc"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("SELECT * FROM t1"),
+                expected, true);
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - 2 updatable resultsets going against the same table
+     */
+    public void testTwoResultSetsDeletingSameRow() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        Statement stmt1 = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1");
+        assertTrue("FAIL - row not found", rs.next());
+        ResultSet rs1 = stmt1.executeQuery("SELECT * FROM t1 FOR UPDATE");
+        assertTrue("FAIL - row not found", rs1.next());
+        println("delete using first resultset");
+        rs.deleteRow();
+        try {
+            // row already deleted by other result set
+            rs1.deleteRow();
+            fail("FAIL - delete using second resultset succedded? ");
+        } catch (SQLException e) {
+            assertSQLState("24000", e);
+        }
+        // Move to next row in the 2nd resultset and then delete using the
+        // second resultset
+        assertTrue("FAIL - row not found", rs1.next());
+        rs1.deleteRow();
+        rs.close();
+        rs1.close();
+        
+        // verify that the table was correctly update
+        String[][] expected = {{"3", "cc"}};
+        JDBC.assertFullResultSet(stmt.executeQuery("SELECT * FROM t1"),
+                expected, true);
+        stmt.close();
+        stmt1.close();
+    }
+    
+    /**
+     * Positive test - setting the fetch size to > 1 will be ignored by
+     * updatable resultset. Same as updatable cursors
+     */
+    public void testSetFetchSizeOnUpdatableResultSet() throws SQLException {
+        createTableT1();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        stmt.executeUpdate("call SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(1)");
+        stmt.setFetchSize(200);
+        ResultSet rs = stmt.executeQuery("SELECT * FROM t1 FOR UPDATE of c1");
+        // Check the Fetch Size in run time statistics output
+        Statement stmt2 = createStatement();
+        ResultSet rs2 = stmt2.executeQuery(
+                "values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS()");
+        while (rs2.next()) {
+            if (rs2.getString(1).startsWith("Fetch Size")) {
+                assertEquals("FAIL - wrong fetch size", "Fetch Size = 1",
+                        rs2.getString(1));
+            }
+        }
+        assertEquals("FAIL - wrong fetch size for updatable cursor",
+                200, stmt.getFetchSize());
+        rs.close();
+        stmt.executeUpdate("call SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(0)");
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - make sure delete trigger gets fired when deleteRow is
+     * issued
+     */
+    public void testDeleteRowWithDeleteTrigger() throws SQLException {
+        createTable0WithTrigger();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        
+        // Verify that before delete trigger got fired, row count is 0 in
+        // deleteTriggerInsertIntoThisTable
+        ResultSet rs = stmt.executeQuery(
+                "select count(*) from deleteTriggerInsertIntoThisTable");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - table shoud contain no rows", 0, rs.getInt(1));
+        rs.close();
+        
+        rs = stmt.executeQuery("SELECT * FROM table0WithTriggers FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column c1", 1, rs.getInt(1));
+        // now try to delete row and make sure that trigger got fired
+        rs.deleteRow();
+        rs.close();
+        
+        // Verify that delete trigger got fired by verifying the row count to
+        // be 1 in deleteTriggerInsertIntoThisTable
+        rs = stmt.executeQuery(
+                "select count(*) from deleteTriggerInsertIntoThisTable");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - table shoud contain one row", 1, rs.getInt(1));
+        rs.close();
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - make sure that update trigger gets fired when updateRow
+     * is issue
+     */
+    public void testUpdateRowWithUpdateTrigger() throws SQLException {
+        createTable0WithTrigger();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        // Verify that before update trigger got fired, row count is 0 in
+        // updateTriggerInsertIntoThisTable
+        ResultSet rs = stmt.executeQuery(
+                "select count(*) from updateTriggerInsertIntoThisTable");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - table shoud contain no rows", 0, rs.getInt(1));
+        rs.close();
+        
+        rs = stmt.executeQuery("SELECT * FROM table0WithTriggers");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column c1", 1, rs.getInt(1));
+        // now try to update row and make sure that trigger got fired
+        rs.updateLong(1,123);
+        rs.updateRow();
+        rs.close();
+        
+        // Verify that update trigger got fired by verifying the row count to
+        // be 1 in updateTriggerInsertIntoThisTable
+        rs = stmt.executeQuery(
+                "select count(*) from updateTriggerInsertIntoThisTable");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - table shoud contain one row", 1, rs.getInt(1));
+        rs.close();
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - Another test case for delete trigger
+     */
+    public void testDeleteRowWithTriggerChangingRS() throws SQLException {
+        createTable1WithTrigger();
+        Statement stmt = createStatement(
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+        ResultSet rs = stmt.executeQuery(
+                "SELECT * FROM table1WithTriggers FOR UPDATE");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong value for column c1", 1, rs.getInt(1));
+        
+        // this delete row will fire the delete trigger which will delete all
+        // the rows from the table and from the resultset
+        rs.deleteRow();
+        try {
+            assertFalse("FAIL - row not found", rs.next());
+            rs.deleteRow();
+            fail("FAIL - there should have be no more rows in the resultset " +
+                    "at this point because delete trigger deleted all the " +
+                    "rows");
+        } catch (SQLException e) {
+            String sqlState = usingEmbedded() ? "24000" : "XCL07";
+            assertSQLState(sqlState, e);
+        }
+        rs.close();
+        
+        // Verify that delete trigger got fired by verifying the row count to
+        // be 0 in table1WithTriggers
+        rs = stmt.executeQuery("select count(*) from table1WithTriggers");
+        assertTrue("FAIL - row not found", rs.next());
+        assertEquals("FAIL - wrong row count", 0, rs.getInt(1));
+        rs.close();
+        stmt.close();
+    }
+    
+    /**
+     * Positive test - Another test case for update trigger
+     */

[... 2692 lines stripped ...]


Mime
View raw message