db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhille...@apache.org
Subject svn commit: r933726 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ client/org/apache/derby/client/net/ drda/org/apache/derby/impl/drda/ engine/org/apache/derby/iapi/reference/ engine/org/apache/derby/iapi/types/ testing/org/apache/d...
Date Tue, 13 Apr 2010 18:08:32 GMT
Author: rhillegas
Date: Tue Apr 13 18:08:32 2010
New Revision: 933726

URL: http://svn.apache.org/viewvc?rev=933726&view=rev
Log:
DERBY-2602: Allow full JDBC nanosecond-precision in timestamps across the network just as
is done in the embedded scenario.

Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/FdocaConstants.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/DRDAConstants.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/junitTests/compatibility/JDBCDriverTest.java

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java Tue Apr 13
18:08:32 2010
@@ -1006,6 +1006,9 @@ public abstract class Connection impleme
      */
     protected abstract boolean serverSupportsLocators();
 
+    /** Return true if the server supports nanoseconds in timestamps */
+    protected abstract boolean serverSupportsTimestampNanoseconds();
+
     public int getTransactionIsolation() throws SQLException {
     	
     	// Store the current auto-commit value and use it to restore 

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java Tue Apr 13 18:08:32
2010
@@ -546,7 +546,8 @@ public abstract class Cursor {
                 dataBuffer_,
                 columnDataPosition_[column - 1],
                 getRecyclableCalendar(), 
-                charsetName_[column - 1]);
+                charsetName_[column - 1],
+                agent_.connection_.serverSupportsTimestampNanoseconds());
     } catch (java.io.UnsupportedEncodingException e) {
              throw new SqlException(agent_.logWriter_, 
                  new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java Tue Apr 13 18:08:32
2010
@@ -22,6 +22,7 @@ package org.apache.derby.client.am;
 
 import org.apache.derby.shared.common.i18n.MessageUtil;
 import org.apache.derby.shared.common.reference.SQLState;
+import org.apache.derby.iapi.reference.DRDAConstants;
 
 import java.io.UnsupportedEncodingException;
 import java.util.Calendar;
@@ -45,7 +46,7 @@ public class DateTime {
 
     private static final int dateRepresentationLength = 10;
     private static final int timeRepresentationLength = 8;
-    private static final int timestampRepresentationLength = 26;
+    private static final int timestampRepresentationLength = DRDAConstants.DRDA_TIMESTAMP_LENGTH;
 
     // *********************************************************
     // ********** Output converters (byte[] -> class) **********
@@ -146,52 +147,53 @@ public class DateTime {
     }
 
     /**
-     * Expected character representation is DERBY string representation of a timestamp:
-     * <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+     * See getTimestampLength() for an explanation of how timestamps are formatted.
      * 
      * @param buffer
      * @param offset
      * @param recyclableCal
      * @param encoding                encoding of buffer
+     * @param supportsTimestampNanoseconds true if the server supports nanoseconds in timestamps
      * @return TimeStamp translated from buffer with specified encoding
      * @throws UnsupportedEncodingException
      */
     public static final java.sql.Timestamp timestampBytesToTimestamp(byte[] buffer,
                                                                      int offset,
                                                                      Calendar recyclableCal,

-                                                                     String encoding) 
+                                                                     String encoding,
+                                                                     boolean supportsTimestampNanoseconds)

     throws UnsupportedEncodingException
     {
         int year, month, day, hour, minute, second, fraction;
-        String timestamp = new String(buffer, offset, 
-                DateTime.timestampRepresentationLength,encoding);
+        String timestamp = new String
+            ( buffer, offset, getTimestampLength( supportsTimestampNanoseconds ), encoding
);
        
         Calendar cal = getCleanCalendar(recyclableCal);
 
         /* java.sql.Timestamp has nanosecond precision, so we have to keep
-         * the parsed microseconds value and use that to set nanos.
+         * the parsed nanoseconds value and use that to set nanos.
          */
-        int micros = parseTimestampString(timestamp, cal);
+        int nanos = parseTimestampString(timestamp, cal, supportsTimestampNanoseconds);
         java.sql.Timestamp ts = new java.sql.Timestamp(cal.getTimeInMillis());
-        ts.setNanos(micros * 1000);
+        ts.setNanos( nanos );
         return ts;
     }
 
     /**
-     * Parse a String of the form <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>
+     * Parse a String of the form <code>yyyy-mm-dd-hh.mm.ss.ffffff[fff]</code>
      * and store the various fields into the received Calendar object.
      *
      * @param timestamp Timestamp value to parse, as a String.
-     * @param cal Calendar into which to store the parsed fields.  Should
-     *  not be null.
+     * @param cal Calendar into which to store the parsed fields.  Should not be null.
+     * @param supportsTimestampNanoseconds true if the server supports nanoseconds in timestamps
      *
-     * @return The microseconds field as parsed from the timestamp string.
+     * @return The nanoseconds field as parsed from the timestamp string.
      *  This cannot be set in the Calendar object but we still want to
      *  preserve the value, in case the caller needs it (for example, to
-     *  create a java.sql.Timestamp with microsecond precision).
+     *  create a java.sql.Timestamp with nanosecond precision).
      */
     private static int parseTimestampString(String timestamp,
-        Calendar cal)
+        Calendar cal, boolean supportsTimestampNanoseconds )
     {
         int zeroBase = ((int) '0');
 
@@ -221,20 +223,28 @@ public class DateTime {
                 10 * (((int) timestamp.charAt(17)) - zeroBase) +
                 (((int) timestamp.charAt(18)) - zeroBase));
 
-        int micros = 
-                100000 * (((int) timestamp.charAt(20)) - zeroBase) +
-                10000 * (((int) timestamp.charAt(21)) - zeroBase) +
-                1000 * (((int) timestamp.charAt(22)) - zeroBase) +
-                100 * (((int) timestamp.charAt(23)) - zeroBase) +
-                10 * (((int) timestamp.charAt(24)) - zeroBase) +
-                (((int) timestamp.charAt(25)) - zeroBase);
-
-        /* The "ffffff" that we parsed is microseconds.  In order to
+        int nanos = 
+                100000000 * (((int) timestamp.charAt(20)) - zeroBase) +
+                10000000 * (((int) timestamp.charAt(21)) - zeroBase) +
+                1000000 * (((int) timestamp.charAt(22)) - zeroBase) +
+                100000 * (((int) timestamp.charAt(23)) - zeroBase) +
+                10000 * (((int) timestamp.charAt(24)) - zeroBase) +
+                1000 * (((int) timestamp.charAt(25)) - zeroBase);
+ 
+        if ( supportsTimestampNanoseconds )
+        {
+            nanos += 100 * (((int) timestamp.charAt(26)) - zeroBase);
+            nanos += 10 * (((int) timestamp.charAt(27)) - zeroBase);
+            nanos += (((int) timestamp.charAt(28)) - zeroBase);
+        }
+        
+        /* The "ffffff[fff]" that we parsed is nanoseconds.  In order to
          * capture that information inside of the MILLISECOND field
-         * we have to divide by 1000.
+         * we have to divide by 1000000.
          */
-        cal.set(Calendar.MILLISECOND, micros / 1000);
-        return micros;
+        cal.set(Calendar.MILLISECOND, nanos / 1000000);
+        
+        return nanos;
     }
 
     // ********************************************************
@@ -328,20 +338,20 @@ public class DateTime {
     }
 
     /**
-     * java.sql.Timestamp is converted to a character representation which is in DERBY string

-     * representation of a timestamp: <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
-     * and then converted to bytes using UTF8 encoding
+     * See getTimestampLength() for an explanation of how timestamps are formatted.
+     *
      * @param buffer  bytes in UTF8 encoding of the timestamp
      * @param offset  write into the buffer from this offset 
      * @param timestamp  timestamp value
-     * @return DateTime.timestampRepresentationLength. This is the fixed 
-     * length in bytes, taken to represent the timestamp value
+     * @param supportsTimestampNanoseconds true if the server supports nanoseconds in timestamps
+     * @return DateTime.timestampRepresentationLength. This is the fixed  length in bytes,
taken to represent the timestamp value
      * @throws SqlException
      * @throws UnsupportedEncodingException
      */
     public static final int timestampToTimestampBytes(byte[] buffer,
                                                       int offset,
-                                                      java.sql.Timestamp timestamp) 
+                                                      java.sql.Timestamp timestamp,
+                                                      boolean supportsTimestampNanoseconds)

     throws SqlException,UnsupportedEncodingException {
         int year = timestamp.getYear() + 1900;
         if (year > 9999) {
@@ -356,8 +366,10 @@ public class DateTime {
         int second = timestamp.getSeconds();
         int microsecond = timestamp.getNanos() / 1000;
 
-        char[] timestampChars = new char[DateTime.timestampRepresentationLength];
+        int arrayLength = getTimestampLength( supportsTimestampNanoseconds );
+        char[] timestampChars = new char[ arrayLength ];
         int zeroBase = (int) '0';
+
         timestampChars[0] = (char) (year / 1000 + zeroBase);
         timestampChars[1] = (char) ((year % 1000) / 100 + zeroBase);
         timestampChars[2] = (char) ((year % 100) / 10 + zeroBase);
@@ -385,13 +397,23 @@ public class DateTime {
         timestampChars[24] = (char) ((microsecond % 100) / 10 + zeroBase);
         timestampChars[25] = (char) (microsecond % 10 + zeroBase);
         
+        if ( supportsTimestampNanoseconds )
+        {
+            int nanosecondsOnly = timestamp.getNanos() % 1000;
+            
+            timestampChars[ 26 ] = (char) (nanosecondsOnly / 100 + zeroBase);
+            timestampChars[ 27 ] = (char) ((nanosecondsOnly % 100) / 10 + zeroBase);
+            timestampChars[ 28 ] = (char) (nanosecondsOnly % 10 + zeroBase);
+        }
+
         // Network server expects to read the timestamp parameter value bytes with
         // UTF-8 encoding.  Reference - DERBY-1127
         // see DRDAConnThread.readAndSetParams
-        byte[] timestampBytes = (new String(timestampChars)).getBytes(Typdef.UTF8ENCODING);
-        System.arraycopy(timestampBytes, 0, buffer, offset, DateTime.timestampRepresentationLength);
+        String newtimestampString = new String(timestampChars);
+        byte[] timestampBytes = newtimestampString.getBytes(Typdef.UTF8ENCODING);
+        System.arraycopy(timestampBytes, 0, buffer, offset, arrayLength);
 
-        return DateTime.timestampRepresentationLength;
+        return arrayLength;
     }
 
     // *********************************************************
@@ -504,8 +526,7 @@ public class DateTime {
     
     
     /**
-     * Expected character representation is DERBY string representation of a timestamp:
-     * <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+     * See getTimestampLength() for an explanation of how timestamps are formatted.
      * 
      * @param buffer
      * @param offset
@@ -547,8 +568,7 @@ public class DateTime {
 
    
     /**
-     * Expected character representation is DERBY string representation of a timestamp:
-     * <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+     * See getTimestampLength() for an explanation of how timestamps are formatted.
      * 
      * @param buffer
      * @param offset
@@ -587,7 +607,7 @@ public class DateTime {
         /* Note that "parseTimestampString()" returns microseconds but we
          * ignore micros because java.sql.Time only has millisecond precision.
          */
-        parseTimestampString(timestamp, cal);
+        parseTimestampString(timestamp, cal, false);
 
         /* Java API indicates that the date components of a Time value
          * must be set to January 1, 1970. So override those values now.
@@ -712,122 +732,21 @@ public class DateTime {
     }
 
     /**
-     * java.sql.Date is converted to character representation that is in DERBY string 
-     * representation of a timestamp:<code>yyyy-mm-dd-hh.mm.ss.ffffff</code>
and then 
-     * converted to bytes using UTF8 encoding and written out to the buffer
-     * @param buffer
-     * @param offset offset in buffer to start writing to
-     * @param date date value
-     * @return DateTime.timestampRepresentationLength. This is the fixed length
-     * in bytes, taken to represent the timestamp value.
-     * @throws SqlException
-     * @throws UnsupportedEncodingException
+     * Return the length of a timestamp depending on whether timestamps
+     * should have full nanosecond precision or be truncated to just microseconds.
+     * java.sql.Timestamp is converted to a character representation which is a DERBY string

+     * representation of a timestamp converted to bytes using UTF8 encoding.
+     * For Derby 10.6 and above, this is <code>yyyy-mm-dd-hh.mm.ss.fffffffff</code>.
+     * For Derby 10.5 and below, this is <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
See DERBY-2602.
+     * and then converted to bytes using UTF8 encoding
+     *
+     * @param supportsTimestampNanoseconds true if the connection supports nanoseconds in
timestamps
      */
-    public static final int dateToTimestampBytes(byte[] buffer,
-                                                 int offset,
-                                                 java.sql.Date date)
-    throws SqlException, UnsupportedEncodingException {
-        int year = date.getYear() + 1900;
-        if (year > 9999) {
-            throw new SqlException(null,
-                new ClientMessageId(SQLState.YEAR_EXCEEDS_MAXIMUM),
-                new Integer(year), "9999");
-        }
-        int month = date.getMonth() + 1;
-        int day = date.getDate();
-
-        char[] timestampChars = new char[DateTime.timestampRepresentationLength];
-        int zeroBase = (int) '0';
-        timestampChars[0] = (char) (year / 1000 + zeroBase);
-        timestampChars[1] = (char) ((year % 1000) / 100 + zeroBase);
-        timestampChars[2] = (char) ((year % 100) / 10 + zeroBase);
-        timestampChars[3] = (char) (year % 10 + +zeroBase);
-        timestampChars[4] = '-';
-        timestampChars[5] = (char) (month / 10 + zeroBase);
-        timestampChars[6] = (char) (month % 10 + zeroBase);
-        timestampChars[7] = '-';
-        timestampChars[8] = (char) (day / 10 + zeroBase);
-        timestampChars[9] = (char) (day % 10 + zeroBase);
-        timestampChars[10] = '-';
-        timestampChars[11] = '0';
-        timestampChars[12] = '0';
-        timestampChars[13] = '.';
-        timestampChars[14] = '0';
-        timestampChars[15] = '0';
-        timestampChars[16] = '.';
-        timestampChars[17] = '0';
-        timestampChars[18] = '0';
-        timestampChars[19] = '.';
-        timestampChars[20] = '0';
-        timestampChars[21] = '0';
-        timestampChars[22] = '0';
-        timestampChars[23] = '0';
-        timestampChars[24] = '0';
-        timestampChars[25] = '0';
-        
-        // Network server expects to read the timestamp parameter value bytes with
-        // UTF-8 encoding.  Reference - DERBY-1127
-        // see DRDAConnThread.readAndSetParams 
-        byte[] timestampBytes = (new String(timestampChars)).getBytes(Typdef.UTF8ENCODING);
-        System.arraycopy(timestampBytes, 0, buffer, offset, DateTime.timestampRepresentationLength);
-
-        return DateTime.timestampRepresentationLength;
+    public static int getTimestampLength( boolean supportsTimestampNanoseconds )
+    {
+        return supportsTimestampNanoseconds ?
+            DRDAConstants.JDBC_TIMESTAMP_LENGTH : DRDAConstants.DRDA_TIMESTAMP_LENGTH;
     }
 
-    /**
-     * java.sql.Time is converted to a character representation that is in DERBY string representation
of a timestamp:
-     * <code>yyyy-mm-dd-hh.mm.ss.ffffff</code> and converted to bytes using UTF8
encoding 
-     * @param buffer
-     * @param offset offset in buffer to start writing to
-     * @param time time value
-     * @return DateTime.timestampRepresentationLength which is the fixed length
-     * taken up by the conversion of time to timestamp in bytes
-     * @throws UnsupportedEncodingException
-     */
-    public static final int timeToTimestampBytes(byte[] buffer,
-                                                 int offset,
-                                                 java.sql.Time time)
-    throws UnsupportedEncodingException {
-        int hour = time.getHours();
-        int minute = time.getMinutes();
-        int second = time.getSeconds();
-
-        char[] timestampChars = new char[DateTime.timestampRepresentationLength];
-        int zeroBase = (int) '0';
-        timestampChars[0] = '1';
-        timestampChars[1] = '9';
-        timestampChars[2] = '0';
-        timestampChars[3] = '0';
-        timestampChars[4] = '-';
-        timestampChars[5] = '0';
-        timestampChars[6] = '1';
-        timestampChars[7] = '-';
-        timestampChars[8] = '0';
-        timestampChars[9] = '1';
-        timestampChars[10] = '-';
-        timestampChars[11] = (char) (hour / 10 + zeroBase);
-        timestampChars[12] = (char) (hour % 10 + zeroBase);
-        timestampChars[13] = '.';
-        timestampChars[14] = (char) (minute / 10 + zeroBase);
-        timestampChars[15] = (char) (minute % 10 + zeroBase);
-        timestampChars[16] = '.';
-        timestampChars[17] = (char) (second / 10 + zeroBase);
-        timestampChars[18] = (char) (second % 10 + zeroBase);
-        timestampChars[19] = '.';
-        timestampChars[20] = '0';
-        timestampChars[21] = '0';
-        timestampChars[22] = '0';
-        timestampChars[23] = '0';
-        timestampChars[24] = '0';
-        timestampChars[25] = '0';
-
-        // Network server expects to read the timestamp parameter value bytes with
-        // UTF-8 encoding.  Reference - DERBY-1127
-        // see DRDAConnThread.readAndSetParams for TIMESTAMP
-        byte[] timestampBytes = (new String(timestampChars)).getBytes(Typdef.UTF8ENCODING);
-        System.arraycopy(timestampBytes, 0, buffer, offset, DateTime.timestampRepresentationLength);
-
-        return DateTime.timestampRepresentationLength;
-    }
 }
 

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java Tue Apr
13 18:08:32 2010
@@ -1764,6 +1764,15 @@ public class NetConnection extends org.a
         return serverSupportsLayerBStreaming();
     }
 
+    /** Return true if the server supports nanoseconds in timestamps */
+    protected final boolean serverSupportsTimestampNanoseconds()
+    {
+        NetDatabaseMetaData metadata =
+            (NetDatabaseMetaData) databaseMetaData_;
+
+        return metadata.serverSupportsTimestampNanoseconds();
+    }
+    
     /**
      * Returns if a transaction is in process
      * @return open

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetDatabaseMetaData.java Tue
Apr 13 18:08:32 2010
@@ -39,6 +39,9 @@ public class NetDatabaseMetaData extends
     /** True if the server supports UDTs */
     private boolean supportsUDTs_;
     
+    /** True if the server supports nanoseconds in timestamps */
+    private boolean supportsTimestampNanoseconds_;
+    
     public NetDatabaseMetaData(NetAgent netAgent, NetConnection netConnection) {
         // Consider setting product level during parse
         super(netAgent, netConnection, new ProductLevel(netConnection.productID_,
@@ -100,6 +103,9 @@ public class NetDatabaseMetaData extends
 
         supportsUDTs_ =
                 productLevel_.greaterThanOrEqualTo(10, 6, 0);
+
+        supportsTimestampNanoseconds_ =
+                productLevel_.greaterThanOrEqualTo(10, 6, 0);
     }
 
     /**
@@ -131,4 +137,12 @@ public class NetDatabaseMetaData extends
     final boolean serverSupportsUDTs() {
         return supportsUDTs_;
     }
+
+    /**
+     * Check if server supports nanoseconds in timestamps
+     * @return true if the server supports this
+     */
+    final boolean serverSupportsTimestampNanoseconds() {
+        return supportsTimestampNanoseconds_;
+    }
 }

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java Tue
Apr 13 18:08:32 2010
@@ -25,6 +25,7 @@ import org.apache.derby.client.am.Lob;
 import org.apache.derby.client.am.Blob;
 import org.apache.derby.client.am.Clob;
 import org.apache.derby.client.am.ColumnMetaData;
+import org.apache.derby.client.am.DateTime;
 import org.apache.derby.client.am.ResultSet;
 import org.apache.derby.client.am.Section;
 import org.apache.derby.client.am.SqlException;
@@ -1260,10 +1261,10 @@ public class NetStatementRequest extends
                     break;
                 case java.sql.Types.TIMESTAMP:
                     // for input, output, and inout parameters
-                    // lid: PROTOCOL_TYPE_NTIME, length overrid: 26
+                    // lid: PROTOCOL_TYPE_NTIMESTAMP, length overrid: 26 or 29
                     // dataFormat: java.sql.Timestamp
                     lidAndLengths[i][0] = DRDAConstants.DRDA_TYPE_NTIMESTAMP;
-                    lidAndLengths[i][1] = 26;
+                    lidAndLengths[i][1] = DateTime.getTimestampLength( netAgent_.netConnection_.serverSupportsTimestampNanoseconds()
);
                     break;
                 case java.sql.Types.BIGINT:
                     // if SQLAM < 6 this should be mapped to decimal (19,0) in common
layer

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java Tue Apr 13 18:08:32
2010
@@ -20,6 +20,7 @@
 */
 package org.apache.derby.client.net;
 
+import org.apache.derby.client.am.DateTime;
 import org.apache.derby.client.am.DisconnectException;
 import org.apache.derby.client.am.ClientMessageId;
 import org.apache.derby.client.am.SqlException;
@@ -1554,9 +1555,12 @@ public class Request {
 
     final void writeTimestamp(java.sql.Timestamp timestamp) throws SqlException {
         try{
-            ensureLength(offset_ + 26);
-            org.apache.derby.client.am.DateTime.timestampToTimestampBytes(bytes_, offset_,
timestamp);
-            offset_ += 26;
+            boolean supportsTimestampNanoseconds = netAgent_.netConnection_.serverSupportsTimestampNanoseconds();
+            int length = DateTime.getTimestampLength( supportsTimestampNanoseconds );
+            ensureLength( offset_ + length );
+            org.apache.derby.client.am.DateTime.timestampToTimestampBytes
+                ( bytes_, offset_, timestamp, supportsTimestampNanoseconds );
+            offset_ += length;
         }catch(UnsupportedEncodingException e) {
             throw new SqlException(netAgent_.logWriter_,  
                     new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/AppRequester.java Tue Apr 13
18:08:32 2010
@@ -302,4 +302,19 @@ class AppRequester
 	protected boolean supportsUDTs() {
 		return (clientType == DNC_CLIENT && greaterThanOrEqualTo(10, 6, 0));
 	}
+
+	protected boolean supportsTimestampNanoseconds() {
+		return (clientType == DNC_CLIENT && greaterThanOrEqualTo(10, 6, 0));
+	}
+
+    /**
+     * The timestamp length may be truncated for old versions of Derby.
+     * See DERBY-2602.
+     */
+    protected int getTimestampLength()
+    {
+        return supportsTimestampNanoseconds() ?
+            DRDAConstants.JDBC_TIMESTAMP_LENGTH : DRDAConstants.DRDA_TIMESTAMP_LENGTH;
+    }
+
 }

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java Tue Apr 13
18:08:32 2010
@@ -4648,7 +4648,9 @@ class DRDAConnThread extends Thread {
 			{
 				// JCC represents ts in a slightly different format than Java standard, so
 				// we do the conversion to Java standard here.
-				String paramVal = reader.readStringData(26).trim();  //parameter may be char value
+                int timestampLength = appRequester.getTimestampLength();
+                
+				String paramVal = reader.readStringData( timestampLength ).trim();  //parameter may be
char value
 				if (SanityManager.DEBUG)
 					trace("ntimestamp parameter value is: "+paramVal);
 				try {
@@ -7706,17 +7708,18 @@ class DRDAConnThread extends Thread {
 					break;
 				case DRDAConstants.DRDA_TYPE_NTIMESTAMP:
 					// we need to send it in a slightly different format, and pad it
-					// up to or truncate it into 26 chars
+					// up to or truncate it to the correct number of characters
+                    int timestampLength = appRequester.getTimestampLength();
 					String ts1 = ((java.sql.Timestamp) val).toString();
 					String ts2 = ts1.replace(' ','-').replace(':','.');
 					int tsLen = ts2.length();
-					if (tsLen < 26)
+					if (tsLen < timestampLength)
 					{
-						for (int i = 0; i < 26-tsLen; i++)
+						for (int i = 0; i < timestampLength-tsLen; i++)
 							ts2 += "0";
 					}
-					else if (tsLen > 26)
-						ts2 = ts2.substring(0,26);
+					else if (tsLen > timestampLength)
+						ts2 = ts2.substring(0,timestampLength);
 					writer.writeString(ts2);
 					break;
 				case DRDAConstants.DRDA_TYPE_NCHAR:

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/FdocaConstants.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/FdocaConstants.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/FdocaConstants.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/FdocaConstants.java Tue Apr 13
18:08:32 2010
@@ -179,7 +179,7 @@ class FdocaConstants
 				break;
 			case java.sql.Types.TIMESTAMP:
 				drdaType = DRDAConstants.DRDA_TYPE_NTIMESTAMP;
-				outlen[0] = 26;
+				outlen[0] = appRequester.getTimestampLength();
 				break;
 			case java.sql.Types.CHAR:
 //				drdaType = DRDAConstants.DRDA_TYPE_NCHAR;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/DRDAConstants.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/DRDAConstants.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/DRDAConstants.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/DRDAConstants.java Tue
Apr 13 18:08:32 2010
@@ -229,4 +229,11 @@ public	interface	DRDAConstants
     public   static final int DB2_SQLTYPE_FAKE_UDT = 2000;
     public   static final int DB2_SQLTYPE_FAKE_NUDT = 2001;
 
+    // DB2 and DRDA support timestamps with microseconds precision, but not
+    // nanoseconds precision: yyyy-mm-dd-hh.mm.ss.ffffff
+    // In contrast, JDBC supports full nanoseconds precision: yyyy-mm-dd-hh.mm.ss.fffffffff
+    //
+    public   static final int DRDA_TIMESTAMP_LENGTH = 26;
+    public   static final int JDBC_TIMESTAMP_LENGTH = 29;
+
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java Tue Apr 13 18:08:32
2010
@@ -28,6 +28,7 @@ import org.apache.derby.catalog.types.Ba
 import org.apache.derby.catalog.types.DecimalTypeIdImpl;
 import org.apache.derby.catalog.types.TypeDescriptorImpl;
 import org.apache.derby.catalog.types.UserDefinedTypeIdImpl;
+import org.apache.derby.iapi.reference.DRDAConstants;
 import org.apache.derby.iapi.reference.JDBC40Translation;
 import org.apache.derby.iapi.reference.Limits;
 import org.apache.derby.iapi.services.io.StoredFormatIds;
@@ -117,7 +118,10 @@ public final class TypeId
         // used as the "precision" for those types.
         public static final int DATE_MAXWIDTH           = 10;	// yyyy-mm-dd
         public static final int TIME_MAXWIDTH           = 8;	// hh:mm:ss
-        public static final int TIMESTAMP_MAXWIDTH      = 26;	// yyyy-mm-dd hh:mm:ss.ffffff
+
+        // I believe that the following is wrong. The format of java.sql.Timestamp.toString()
+        // is yyyy-mm-dd hh:mm:ss.fffffffff
+        public static final int TIMESTAMP_MAXWIDTH      = DRDAConstants.DRDA_TIMESTAMP_LENGTH;
// yyyy-mm-dd hh:mm:ss.ffffff
 
         // Scale DOES exist for time values.  For a TIMESTAMP value,
         // it's 6 ('ffffff'); for a TIME value, it's 0 (because there

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java
Tue Apr 13 18:08:32 2010
@@ -885,11 +885,7 @@ public class ParameterMappingTest extend
                         assertEquals("17:14:24",s);
                         break;
                     case java.sql.Types.TIMESTAMP:
-                    	// DERBY-2602 Client TIMESTAMP is truncated
-                        if (usingEmbedded())
-                            assertEquals("2004-02-14 17:14:24.097625551",s);
-                        else
-                            assertEquals("2004-02-14 17:14:24.097625",s);
+                        assertEquals("2004-02-14 17:14:24.097625551",s);
                         break;
                     case java.sql.Types.CLOB:
                         assertEquals("67",s);
@@ -3613,18 +3609,11 @@ public class ParameterMappingTest extend
             assertNotNull(val);
             break;
         case java.sql.Types.TIMESTAMP:
-        	//DERBY-2602 Client TIMESTAMP is truncated
             if (param == 2)
-                if (usingEmbedded())
-                    assertEquals("2004-03-12 21:14:24.938222433", val.toString());
-                else
-                    assertEquals("2004-03-12 21:14:24.938222", val.toString());
-            else if (param == 3)
-                if (usingEmbedded())
-                    assertEquals("2004-04-12 04:25:26.462983731", val.toString());
-                else
-                    assertEquals("2004-04-12 04:25:26.462983", val.toString());
-            break;
+                assertEquals("2004-03-12 21:14:24.938222433", val.toString());
+            else if (param == 3)
+                assertEquals("2004-04-12 04:25:26.462983731", val.toString());
+           break;
         }
     }
 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/junitTests/compatibility/JDBCDriverTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/junitTests/compatibility/JDBCDriverTest.java?rev=933726&r1=933725&r2=933726&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/junitTests/compatibility/JDBCDriverTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/junitTests/compatibility/JDBCDriverTest.java
Tue Apr 13 18:08:32 2010
@@ -252,12 +252,54 @@ public	class	JDBCDriverTest	extends	Comp
 
 		datatypesTest( conn );
         udtTest( conn );
+        derby_2602_test( conn );
 
 		close( conn );
 	}
 	
 	/////////////////////////////////////////////////////////////
 	//
+	//	DERBY-2602
+	//
+	/////////////////////////////////////////////////////////////
+
+    //
+    // Verify that timestamps retain their nanosecond-precision
+    // across the network from release 10.6 onward.
+    //
+	private	void	derby_2602_test( Connection conn )
+		throws Exception
+	{
+        //
+        // We must expect truncation of timestamps in a network configuration
+        // unless both the client and the server are at 10.6 or higher.
+        // See DERBY-2602.
+        //
+        boolean correctBehavior =
+            usingEmbeddedClient() ||
+            (
+             getServerVersion().atLeast( DRB_10_6 ) &&
+             getDriverVersion().atLeast( DRB_10_6 )
+             );
+
+        Timestamp ts = Timestamp.valueOf("2004-02-14 17:14:24.976255123");
+		PreparedStatement	insert = prepare( conn, "insert into t_2602( a ) values ( ? )" );
+        insert.setTimestamp(1,ts);
+        insert.executeUpdate();
+        insert.close();
+
+		PreparedStatement	select = prepare( conn, "select a from t_2602" );
+        ResultSet selectRS = select.executeQuery();
+        selectRS.next();
+        Timestamp resultTS = selectRS.getTimestamp( 1 );
+        int resultNanos = resultTS.getNanos();
+
+        int expectedResult = correctBehavior ? 976255123  : 976255000;
+        assertEquals( expectedResult, resultNanos );
+    }
+    
+	/////////////////////////////////////////////////////////////
+    //
 	//	TEST UDTs
 	//
 	/////////////////////////////////////////////////////////////
@@ -1030,6 +1072,7 @@ public	class	JDBCDriverTest	extends	Comp
 		createTable( conn, ALL_TYPES_TABLE, ALL_TYPES );
 
         createUDTObjects( conn );
+        create_derby_2602_objects( conn );
 	}
 
 	//
@@ -1096,6 +1139,18 @@ public	class	JDBCDriverTest	extends	Comp
         ps.close();
     }
 
+    //
+    // Create a table with a timestamp column.
+    //
+    private void create_derby_2602_objects( Connection conn ) throws Exception
+    {
+        PreparedStatement ps;
+
+        ps = conn.prepareStatement( "create table t_2602( a timestamp )\n" );
+        ps.execute();
+        ps.close();
+    }
+
 
 	//
 	// Helper methods for declaring a table.
@@ -1123,6 +1178,7 @@ public	class	JDBCDriverTest	extends	Comp
 	{
 		dropTable( conn, ALL_TYPES_TABLE );
         dropUDTObjects( conn );
+        drop_derby_2602_objects( conn );
 	}
 
     //
@@ -1138,6 +1194,14 @@ public	class	JDBCDriverTest	extends	Comp
         dropUDT( conn, "PRICE" );
     }
 
+    //
+    // Drop objects needed by DERBY-2602 tests.
+    //
+    private void drop_derby_2602_objects( Connection conn )
+    {
+        dropTable( conn, "T_2602" );
+    }
+
 	//
 	// Logic for stuffing a data value into a column, given its type.
 	//



Mime
View raw message