You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by dj...@apache.org on 2006/09/06 18:20:34 UTC

svn commit: r440762 - /db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TimeHandlingTest.java

Author: djd
Date: Wed Sep  6 09:20:34 2006
New Revision: 440762

URL: http://svn.apache.org/viewvc?view=rev&rev=440762
Log:
DERBY-1700 (partial) Add JUnit lang/TimeHandlingTest that perfoms tests on CURRENT TIME and CURRENT TIMESTAMP
and can be exapnded to test CURRENT DATE and other date & time functionality.

Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TimeHandlingTest.java

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TimeHandlingTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TimeHandlingTest.java?view=diff&rev=440762&r1=440761&r2=440762
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TimeHandlingTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TimeHandlingTest.java Wed Sep  6 09:20:34 2006
@@ -20,13 +20,14 @@
  */
 package org.apache.derbyTesting.functionTests.tests.lang;
 
-import java.sql.Connection;
 import java.sql.Date;
+import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Time;
 import java.sql.Timestamp;
+import java.sql.Types;
 import java.util.Calendar;
 
 import junit.framework.Test;
@@ -37,39 +38,32 @@
 
 
 public class TimeHandlingTest extends BaseJDBCTestCase {
-
-    private static long SLEEP_TIME = 2000;
     
-    private Calendar cal;
+    /**
+     * All the functions or expressions that result in
+     * a TIME value with the same value as CURRENT_TIME.
+     */
+    private static final String[] CURRENT_TIME_FUNCTIONS =
+    {"CURRENT TIME", "CURRENT_TIME"};
     
-    // Determine a minimal sleep time that that consistently, based upon
-    // ten tries, results in a change in System.currentTimeMillis.
-    static {
-        for (int ms = 50; ms <= 2000; ms +=50)
-        {
-            boolean seenChange = true;
-            for (int i = 0; i < 10; i++) {
-                long start = System.currentTimeMillis();
-                try {
-                    Thread.sleep(ms);
-                } catch (InterruptedException e) {
-                    seenChange = false;
-                }
-                long end = System.currentTimeMillis();
-                
-                if (start == end) {
-                    seenChange = false;
-                    break;
-                }
-            }
-            
-            if (seenChange) {
-                SLEEP_TIME = ms;
-                break;
-            }
-        }
-    }
+    /**
+     * All the functions or expressions that result in
+     * a TIMESTAMP value with the same value as CURRENT_TIMESTAMP.
+     */
+    private static final String[] CURRENT_TIMESTAMP_FUNCTIONS =
+    {"CURRENT TIMESTAMP", "CURRENT_TIMESTAMP"};    
+
+    /**
+     * Time to sleep that will result in different TIME values.
+     */
+    private static final long SLEEP_TIME = 2000;
     
+    /**
+     * Calendar for testing returned values.
+     */
+    private Calendar cal;
+
+
     public static Test suite()
     {
         TestSuite suite = new TestSuite(TimeHandlingTest.class);
@@ -86,19 +80,28 @@
                 s.execute("CREATE TABLE TIME_ALL (ID INT," +
                         " C_T TIME," +
                         " C_D DATE," +
-                        " C_TS TIMESTAMP," +
-                        " D_T TIME DEFAULT CURRENT TIME," +
-                        " D_D DATE  DEFAULT CURRENT DATE," +
-                        " D_TS TIMESTAMP DEFAULT CURRENT TIMESTAMP)");
-
-            }
+                        " C_TS TIMESTAMP)");
+                
+                for (int f = 0; f < CURRENT_TIME_FUNCTIONS.length; f++)
+                {
+                    s.execute("ALTER TABLE TIME_ALL ADD COLUMN" +
+                            " D_T" + f + " TIME WITH DEFAULT " +
+                            CURRENT_TIME_FUNCTIONS[f]);
+                }
+                for (int f = 0; f < CURRENT_TIMESTAMP_FUNCTIONS.length; f++)
+                {
+                    s.execute("ALTER TABLE TIME_ALL ADD COLUMN" +
+                            " D_TS" + f + " TIMESTAMP WITH DEFAULT " +
+                            CURRENT_TIMESTAMP_FUNCTIONS[f]);
+                }
+           }
         };
     }
     
     /**
-     * Method for SQL SLEEP function. Sleeps for the time determined
-     * at class initialization that will result in a change in
-     * System.currentTimeMillis.
+     * Method for SQL SLEEP function. Sleeps for the time 
+     * that will result in a change in
+     * System.currentTimeMillis and a Derby TIME value.
      * @return
      * @throws InterruptedException
      */
@@ -122,99 +125,274 @@
     /**
      * Tests for CURRENT TIME and CURRENT_TIME.
      * A set of tests that ensure the CURRENT TIME maintains
-     * a single value for the life time of a statement.
+     * a single value for the life time of a statement and
+     * that (subject to the resolution) the returned value
+     * is correctly between the start time of the statement
+     * execution and the first fetch or completion.
      * @throws SQLException
+     * @throws InterruptedException 
      */
-    public void testCurrentTime() throws SQLException
+    public void testCurrentTime() throws SQLException, InterruptedException
+    {      
+        currentFunctionTests(Types.TIME, CURRENT_TIME_FUNCTIONS);      
+    }
+    
+    /**
+     * Tests for CURRENT TIMESTAMP functions.
+     * A set of tests that ensure the CURRENT TIMESTAMP maintains
+     * a single value for the life time of a statement and
+     * that (subject to the resolution) the returned value
+     * is correctly between the start time of the statement
+     * execution and the first fetch or completion.
+     * @throws SQLException
+     * @throws InterruptedException 
+     */
+    public void testCurrentTimestamp() throws SQLException, InterruptedException
+    {      
+        currentFunctionTests(Types.TIMESTAMP, CURRENT_TIMESTAMP_FUNCTIONS);      
+    }    
+    /**
+     * Test all the current timedate functions passed in that
+     * return the specified type. Generic function that checks
+     * the functions' are all identical in various situations
+     * and that the have the correct value, and change across
+     * executions.
+     * 
+     * @param jdbcType JDBC type, Types.TIME, DATE or TIMESTAMP.
+     * @param functions List of functions or expressions that map to the
+     * current time date value and return the specified type.
+     * @throws SQLException
+     * @throws InterruptedException 
+     */
+    private void currentFunctionTests(int jdbcType, String[] functions)
+    throws SQLException, InterruptedException
     {
         Statement s = createStatement();
+
+        // Single value returned by each function.
+        for (int f = 0; f < functions.length; f++) {
+            checkCurrentQuery(jdbcType, s, "VALUES " + functions[f],
+                    new int[] {1}, 1);
+        }
         
-        // Simple CURRENT_TIME
-        long start = System.currentTimeMillis();
-        ResultSet rs = s.executeQuery("VALUES CURRENT TIME");
-        rs.next();
-        long end = System.currentTimeMillis();
-        checkCurrentTimeValue(start, end, rs, 1);        
-        rs.close();
-        
-        // Alternate CURRENT TIME
-        start = System.currentTimeMillis();
-        rs = s.executeQuery("VALUES CURRENT_TIME");
-        rs.next();
-        end = System.currentTimeMillis();
-        checkCurrentTimeValue(start, end, rs, 1);
-        rs.close();
+        // Create text for a single row in a VALUES clause,
+        // each function represented once.
+        StringBuffer rb = new StringBuffer("(");
+        for (int f = 0; f < functions.length; f++) {
+            if (f != 0)
+                rb.append(", ");
+            rb.append(functions[f]);
+        }
+        rb.append(")");
+        String row = rb.toString();
         
-        // Check they produce the same value
-        start = System.currentTimeMillis();
-        rs = s.executeQuery("VALUES (CURRENT_TIME, CURRENT TIME)");
-        rs.next();
-        end = System.currentTimeMillis();
-        checkCurrentTimeMultiple(start, end, rs, new int[] {1,2}, 2);
-        rs.close();
+        int[] columns = new int[functions.length];
+        for (int f = 0; f < columns.length; f++)
+            columns[f] = f + 1;
+        
+        // All the functions as a single row, all return the same value
+        String sql = "VALUES " + row;
+        checkCurrentQuery(jdbcType, s, sql, columns, functions.length);
 
-        // Check they produce the same value across multiple rows
-        start = System.currentTimeMillis();
-        rs = s.executeQuery(
-                "VALUES (CURRENT_TIME, CURRENT TIME), (CURRENT_TIME, CURRENT TIME),(CURRENT_TIME, CURRENT TIME)");
-        rs.next();
-        end = System.currentTimeMillis();       
-        checkCurrentTimeMultiple(start, end, rs, new int[] {1,2}, 6);
-        rs.close();
         
         // Check they produce the same value across multiple rows
+        sql = "VALUES " + row + "," + row + "," + row;
+        checkCurrentQuery(jdbcType, s, sql, columns, 3 * functions.length);
+
+        // Check they produce the same value across multiple rows
         // with a forced sleep within row creaton
-        start = System.currentTimeMillis();
-        rs = s.executeQuery(
-                "VALUES (CURRENT_TIME, CURRENT TIME, SLEEP())," +
-                " (CURRENT_TIME, CURRENT TIME, SLEEP())," +
-                " (CURRENT_TIME, CURRENT TIME, SLEEP())");
-        rs.next();
-        end = System.currentTimeMillis();       
-        checkCurrentTimeMultiple(start, end, rs, new int[] {1,2}, 6);
-        rs.close(); 
+        String sleepRow = row.substring(0, row.length() - 1)
+             + ", SLEEP())";
+        
+        sql =  "VALUES " + sleepRow + "," + sleepRow + "," + sleepRow;
+        checkCurrentQuery(jdbcType, s, sql, columns, 3 * functions.length);
+
         
         // Check behaviour in non-queries.
+        String ccol = null;
+        String dcol = null;
+        switch (jdbcType)
+        {
+        case Types.TIME:
+            dcol = "D_T";
+            ccol = "C_T";
+            break;
+        case Types.TIMESTAMP:
+            dcol = "D_TS";
+            ccol = "C_TS";
+            break;            
+        case Types.DATE:
+            dcol = "D_D";
+            ccol = "C_D";
+            break; 
+        default:
+            fail("Unexpected JDBC Type " + jdbcType);
+        }
         
-        // Simple insert of a single row
-        s.executeUpdate("DELETE FROM TIME_ALL");
-        start = System.currentTimeMillis();
-        s.executeUpdate("INSERT INTO TIME_ALL(C_T) VALUES CURRENT TIME");
-        end = start = System.currentTimeMillis();
-        rs = s.executeQuery("SELECT C_T, D_T FROM TIME_ALL");
-        rs.next();
-        checkCurrentTimeMultiple(start, end, rs, new int[] {1,2}, 2);
-        rs.close();
+        // All the functions as multiple rows,  one function per row.
+        StringBuffer rm = new StringBuffer();
+        for (int f = 0; f < functions.length; f++) {
+            if (f != 0)
+                rm.append(", ");
+            rm.append(functions[f]);
+        }
+        String mrow = rm.toString();
         
-        // Insert of multiple rows
+        // Select list with all the columns of this type
+        StringBuffer sb = new StringBuffer();
+        sb.append(ccol); // Column without the defaul
+        for (int f = 0; f < functions.length; f++) {
+            sb.append(", ");
+            sb.append(dcol);
+            sb.append(f);
+        }
+        String typeColumnList = sb.toString();
+        String selectAllType = "SELECT " + typeColumnList + " FROM TIME_ALL";
+        
+        int[] tableColumns = new int[columns.length + 1];
+        for (int i = 0; i < tableColumns.length; i++)
+            tableColumns[i] = i+1;
+                    
+        // Insert multiple rows, one per function
+        // Check all the inserted value and the default
+        // columns have the same value.
+        String insert = "INSERT INTO TIME_ALL(" + ccol + ") VALUES " + mrow;
         s.executeUpdate("DELETE FROM TIME_ALL");
-        start = System.currentTimeMillis();
-        s.executeUpdate("INSERT INTO TIME_ALL(C_T) VALUES CURRENT TIME, CURRENT TIME, CURRENT TIME, CURRENT_TIME");
-        end = start = System.currentTimeMillis();
-        rs = s.executeQuery("SELECT C_T, D_T FROM TIME_ALL");
+        long start = System.currentTimeMillis();
+        s.executeUpdate(insert);
+        long end = System.currentTimeMillis();
+        ResultSet rs = s.executeQuery(selectAllType);
         rs.next();
-        checkCurrentTimeMultiple(start, end, rs, new int[] {1,2}, 8);
+        checkCurrentMultiple(jdbcType, start, end, rs, tableColumns, 
+                functions.length * (functions.length + 1));
         rs.close();
         
         // Insert of multiple rows from a query with a delay
+        // All the functions as multiple rows,  one function per row
+        // with a SLEEP as the first column.
+        sb = new StringBuffer();
+        for (int f = 0; f < functions.length; f++) {
+            if (f != 0)
+                sb.append(", ");
+            sb.append("(SLEEP(), ");
+            sb.append(functions[f]);
+            sb.append(")");
+        }
+        String mSleepRow = sb.toString();
+        
+        insert = "INSERT INTO TIME_ALL(ID, " + ccol + ") " +
+          " SELECT * FROM TABLE (VALUES " +
+          mSleepRow +
+          ") AS T";
+       
         s.executeUpdate("DELETE FROM TIME_ALL");
         start = System.currentTimeMillis();
-        s.executeUpdate("INSERT INTO TIME_ALL(ID, C_T) " +
-                " SELECT * FROM TABLE (VALUES " +
-                " (SLEEP(), CURRENT TIME), " +
-                " (SLEEP(), CURRENT TIME), " +
-                " (SLEEP(), CURRENT TIME), " +
-                " (SLEEP(), CURRENT TIME)) AS T");
-        end = start = System.currentTimeMillis();
-        rs = s.executeQuery("SELECT C_T, D_T FROM TIME_ALL");
+        s.executeUpdate(insert);
+        end = System.currentTimeMillis();
+        rs = s.executeQuery(selectAllType);
         rs.next();
-        checkCurrentTimeMultiple(start, end, rs, new int[] {1,2}, 8);
-        rs.close();        
-         
+        checkCurrentMultiple(jdbcType, start, end, rs, tableColumns,
+                functions.length * (functions.length + 1));
+        rs.close();
+        
+        // Ensure a PreparedStatement (psI) resets its current time correctly
+        // and does not get stuck with a single value for all executions.
+        PreparedStatement psQ = prepareStatement(
+                selectAllType + " WHERE ID = ?");
+        
+        Object last = null;
+        for (int f = 0; f < functions.length; f++) {
+            PreparedStatement psI = prepareStatement("INSERT INTO TIME_ALL(ID, " +
+                    ccol + ")" +
+                    " VALUES (?, " + functions[f] +")");
+            s.executeUpdate("DELETE FROM TIME_ALL");
+
+            for (int i = 1; i <=3; i++) {
+               psI.setInt(1, i);
+               psQ.setInt(1, i);   
+               start = System.currentTimeMillis();
+               psI.executeUpdate();
+               end = System.currentTimeMillis();
+
+               rs = psQ.executeQuery();
+               rs.next();
+               Object next = checkCurrentMultiple(jdbcType, start, end, rs,
+                       tableColumns, functions.length + 1);
+               rs.close();
+               
+               if (last != null) {
+                   // This check is redundant because the last and next have
+                   // been checked they are within limit of the start and end.
+                   // But why not check it.
+                   assertFalse("CURRENT value not changed over executions",
+                           last.equals(next));
+               }
+               last = next;
+                     
+               // Ensure the next execution is meant to get a different value
+               Thread.sleep(SLEEP_TIME);
+            }
+            psI.close();
+
+        }
+
+        psQ.close();
         s.close();
     }
     
     /**
+     * Execute a query that uses CURRENT expressions directly.
+     * The time returned for these values should be between the
+     * start of execution and after the return from the first rs.next().
+     * @param sqlType
+     * @param s
+     * @param sql
+     * @param columns
+     * @param expectedCount
+     * @throws SQLException
+     */
+    private void checkCurrentQuery(int sqlType,
+            Statement s, String sql, int[] columns, int expectedCount)
+    throws SQLException
+    {
+        long start = System.currentTimeMillis();
+        ResultSet rs = s.executeQuery(sql);
+        rs.next();
+        long end = System.currentTimeMillis();
+        checkCurrentMultiple(sqlType, start, end, rs,
+                columns, expectedCount);
+        rs.close();       
+    }
+    
+    /**
+     * Check the validity of all CURRENT time values returned and
+     * that they are identical.
+     * @param jdbcType Types.TIME or TIMESTAMP
+     * @param start Start of window for valid value.
+     * @param end End of window for valid value.
+     * @param rs Result set positioned  on row.
+     * @param columns Columns holding current values.
+     * @param expectedCount Total number of values exected to see
+     * (row count times column count)
+     * @return
+     * @throws SQLException
+     */
+    private Object checkCurrentMultiple(int jdbcType, long start, long end, ResultSet rs,
+            int[] columns, int expectedCount) throws SQLException
+   {
+        switch (jdbcType)
+        {
+        case Types.TIME:
+            return checkCurrentTimeMultiple(start, end, rs, columns, expectedCount);
+        case Types.TIMESTAMP:
+            return checkCurrentTimestampMultiple(start, end, rs, columns, expectedCount);
+        default:
+            fail("Unexpected type " + jdbcType);
+        return null;
+        }
+  }
+    
+    /**
      * Check a set of rows and columns with values set to CURRENT TIME
      * in a single statement are the same.
      * @param start Start time for the statement that set the values.
@@ -224,7 +402,7 @@
      * @param expectedCount Number of values we are execpted to check.
      * @throws SQLException
      */
-    private void checkCurrentTimeMultiple(long start, long end, ResultSet rs,
+    private Time checkCurrentTimeMultiple(long start, long end, ResultSet rs,
             int[] columns, int expectedCount) throws SQLException
     {   
         // Result set is positioned on starting row
@@ -254,8 +432,52 @@
         }
         
         assertEquals(expectedCount, count);
+        
+        return base;
     }
-    
+    /**
+     * Check a set of rows and columns with values set to CURRENT TIMESTAMP
+     * in a single statement are the same.
+     * @param start Start time for the statement that set the values.
+     * @param end End time for the statement that set the values.
+     * @param rs ResultSet positioned on the first row.
+     * @param columns Set of columns holding the TIME values
+     * @param expectedCount Number of values we are execpted to check.
+     * @throws SQLException
+     */
+    private Timestamp checkCurrentTimestampMultiple(long start, long end, ResultSet rs,
+            int[] columns, int expectedCount) throws SQLException
+    {   
+        // Result set is positioned on starting row
+        // Since all values must be the same since they are based upon
+        // CURRENT TIME from a single statement, pick one as the base
+        // and compare the rest to it.
+        Timestamp base = checkCurrentTimestampValue(start, end, rs, columns[0]);
+        assertNotNull(base);
+        int count = 1;
+        
+        // check the remaining columns on this row.
+        for (int i = 1; i < columns.length; i++)
+        {
+            Timestamp ts = checkCurrentTimestampValue(start, end, rs, columns[i]);
+            assertEquals("CURENT TIMESTAMP changed during execution", base, ts);
+            count++;
+        }
+        
+        // now check all columns on any remaining rows
+        while (rs.next()) {
+            for (int i = 0; i < columns.length; i++)
+            {
+                Timestamp ts = checkCurrentTimestampValue(start, end, rs, columns[i]);
+                assertEquals("CURENT TIMESTAMP changed during execution", base, ts);
+                count++;
+            }
+        }
+        
+        assertEquals(expectedCount, count);
+        
+        return base;
+    }    
     /**
      * Check the consistency of a ResultSet column that returns
      * a TIME value. Can be used for any column of type TIME.
@@ -278,18 +500,23 @@
   
         Time tv = rs.getTime(column);
         assertEquals(tv == null, rs.wasNull());
-        if (tv == null)
+        
+        Object ov = rs.getObject(column);
+        assertEquals(ov == null, rs.wasNull());
+        
+        if (tv == null) {
+            assertNull(ov);
             return null;
+        }
         
+        assertTrue(ov instanceof java.sql.Time);
+        assertEquals(tv, ov);
+         
         // Check the date portion is set to 1970/01/01
-        assertTime19700101(tv);
+        assertTime1970(tv);
         cal.clear();
         cal.setTime(tv);
         
-        int hour = cal.get(Calendar.HOUR_OF_DAY);
-        int min = cal.get(Calendar.MINUTE);
-        int sec = cal.get(Calendar.SECOND);
-        
         // Check the milli-seconds portion is 0
         // Derby does not support that precision in TIME
         assertEquals(0, cal.get(Calendar.MILLISECOND));
@@ -300,12 +527,7 @@
         assertFalse(rs.wasNull());
         
         // Check the TIME portion is set to the same as tv
-        cal.clear();
-        cal.setTime(tsv);
-        assertEquals(hour, cal.get(Calendar.HOUR_OF_DAY));
-        assertEquals(min, cal.get(Calendar.MINUTE));
-        assertEquals(sec, cal.get(Calendar.SECOND));
-        assertEquals(0, cal.get(Calendar.MILLISECOND));
+        assertTimeEqual(tv, tsv);
         
         // DERBY-1811, DERBY-889 being fixed could add tests
         // here to check the returned date portion is the current date
@@ -325,9 +547,62 @@
     
     /**
      * Check the consistency of a ResultSet column that returns
+     * a TIMESTAMP value. Can be used for any column of type TIMESTAMP.
+     * 
+     * @param rs ResultSet holding the column, positioned on a row
+     * @param column Column with the TIMESTAMP value.
+     * @return Returns the Time object obtained from the column.
+     * @throws SQLException
+     */
+    private Timestamp checkTimestampValue(ResultSet rs, int column) throws SQLException
+    {
+        assertEquals(java.sql.Types.TIMESTAMP,
+                rs.getMetaData().getColumnType(column));
+        
+  
+        Timestamp tsv = rs.getTimestamp(column);
+        assertEquals(tsv == null, rs.wasNull());
+       
+        Object ov = rs.getObject(column);
+        assertEquals(ov == null, rs.wasNull());
+        
+        if (tsv == null) {
+            assertNull(ov);
+            return null;
+        }
+
+        assertTrue(ov instanceof java.sql.Timestamp);
+        assertEquals(tsv, ov);
+       
+        Time tv = rs.getTime(column);
+        assertNotNull(tv);
+        assertFalse(rs.wasNull());
+ 
+        // Check the date portion is set to 1970/01/01
+        assertTime1970(tv);
+
+        // Check the TIME portion is set to the same as tv
+        // DERBY-1816 java.sql.Time values from TIMESTAMP
+        // colummns lose their precision with client.
+        if (!usingDerbyNetClient())
+            assertTimeEqual(tv, tsv);
+               
+        String sv = rs.getString(column);
+        assertNotNull(sv);
+        assertFalse(rs.wasNull());
+        
+        // Assert the string converted back into a Time matches the Time returned.
+        assertEquals("ResultSet String converted to java.sql.Timestamp mismatch",
+                tsv, Timestamp.valueOf(sv));
+        
+        return tsv;
+    }    
+
+    /**
+     * Check the consistency of a ResultSet column that returns
      * CURRENT TIME or a value set from CURRENT TIME.
      * 
-     * @param start Time the query was executed
+     * @param start Time the statement settng the value was executed
      * @param end Time after first rs.next() or update statement was executed
      * @param rs ResultSet holding the column, positioned on a row
      * @param column Column with the timestamp.
@@ -368,7 +643,51 @@
         
         return tv;
     }
-    
+    /**
+     * Check the consistency of a ResultSet column that returns
+     * CURRENT TIMESTAMP or a value set from CURRENT TIMESTAMP.
+     * 
+     * @param start Time the statement settng the value was executed
+     * @param end Time after first rs.next() or update statement was executed
+     * @param rs ResultSet holding the column, positioned on a row
+     * @param column Column with the timestamp.
+     * @return Returns the Timestamp object obtained from the column.
+     * @throws SQLException
+     */
+    private Timestamp checkCurrentTimestampValue(long start, long end,
+            ResultSet rs, int column) throws SQLException
+    {       
+        Timestamp tsv = checkTimestampValue(rs, column);
+
+        // The time returned should be between the value
+        // of start and end (inclusive of both)
+        
+        Timestamp st = new Timestamp(start);
+        Timestamp et = new Timestamp(end);
+        
+        
+        if (st.after(et)) {
+            // Gone back in time!
+            // Well test was running around midnight and the
+            // time for the start time is equal to or before 23:59:59
+            // and end time is equal to or after  00:00:00
+            
+            assertTrue("CURRENT TIME outside of range when test crossing midnight",
+               (tsv.equals(st) || tsv.after(st))
+               || (tsv.equals(et) || tsv.before(et)));
+        }
+        else
+        {
+            // End time is after or equal to start time, expected case.
+
+            // The returned time must not be before the
+            // start time or after the end time.
+            assertFalse("CURRENT TIME before start of statement", tsv.before(st));
+            assertFalse("CURRENT TIME after end of statement", tsv.after(et));       
+        }
+        
+        return tsv;
+    }  
     /**
      * Create a Time object that has its date components
      * set to 1970/01/01 and its time to match the time
@@ -389,7 +708,7 @@
         cal.set(Calendar.MILLISECOND, 0);
         
         Time to =  new Time(cal.getTime().getTime());
-        assertTime19700101(to);
+        assertTime1970(to);
         return to;
     }
     
@@ -413,7 +732,7 @@
         cal.set(Calendar.MILLISECOND, 0);
         
         Time to =  new Time(cal.getTime().getTime());
-        assertTime19700101(to);
+        assertTime1970(to);
         return to;
     }
     
@@ -424,7 +743,7 @@
      * it is up to the driver.
      * @param t
      */
-    private void assertTime19700101(Time t){
+    private void assertTime1970(Time t) {
         
         /* Cannot do this because all these methods
          * throw IllegalArgumentException by definition,
@@ -440,5 +759,30 @@
         assertEquals(1970, cal.get(Calendar.YEAR));
         assertEquals(Calendar.JANUARY, cal.get(Calendar.MONTH));
         assertEquals(1, cal.get(Calendar.DATE));
+    }
+    
+    /**
+     * Assert the time portion of a java.sql.Timestamp
+     * is equal to the value of a java.sql.Time.
+     * @param tv
+     * @param tsv
+     */
+    private void assertTimeEqual(Time tv, Timestamp tsv)
+    {
+        cal.clear();
+        cal.setTime(tv);
+                
+        int hour = cal.get(Calendar.HOUR_OF_DAY);
+        int min = cal.get(Calendar.MINUTE);
+        int sec = cal.get(Calendar.SECOND);
+        int ms = cal.get(Calendar.MILLISECOND);
+                        
+        // Check the time portion is set to the same as tv
+        cal.clear();
+        cal.setTime(tsv);
+        assertEquals(hour, cal.get(Calendar.HOUR_OF_DAY));
+        assertEquals(min, cal.get(Calendar.MINUTE));
+        assertEquals(sec, cal.get(Calendar.SECOND));
+        assertEquals(ms, cal.get(Calendar.MILLISECOND));
     }
 }