[libpostgresql-jdbc-java] 08/09: Backport to 7.3 of patch to correctly handle fractional seconds

Emmanuel Bourg ebourg-guest at moszumanska.debian.org
Mon Jan 9 10:19:00 UTC 2017


This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to tag REL7_3_2
in repository libpostgresql-jdbc-java.

commit 9fc2ea89271d39d49d0213a8fde09e54a88f7b1a
Author: Barry Lind <barry at xythos.com>
Date:   Tue Jan 14 09:15:35 2003 +0000

    Backport to 7.3 of patch to correctly handle fractional seconds
    
     Modified Files:
      Tag: REL7_3_STABLE
     	jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
     	jdbc/org/postgresql/test/jdbc2/TimestampTest.java
---
 org/postgresql/jdbc1/AbstractJdbc1ResultSet.java | 71 +++++++++++++++++-------
 org/postgresql/test/jdbc2/TimestampTest.java     | 43 ++++++++++----
 2 files changed, 81 insertions(+), 33 deletions(-)

diff --git a/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java b/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
index 4a835f2..84493cd 100644
--- a/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
+++ b/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
@@ -844,7 +844,14 @@ public abstract class AbstractJdbc1ResultSet
 	* Java also expects fractional seconds to 3 places where postgres
 	* will give, none, 2 or 6 depending on the time and postgres version.
 	* From version 7.2 postgres returns fractional seconds to 6 places.
-	* If available, we drop the last 3 digits.
+	*
+	* According to the Timestamp documentation, fractional digits are kept
+	* in the nanos field of Timestamp and not in the milliseconds of Date.
+	* Thus, parsing for fractional digits is entirely separated from the
+	* rest.
+	*
+	* The method assumes that there are no more than 9 fractional
+	* digits given. Undefined behavior if this is not the case.
 	*
 	* @param s		   The ISO formated date string to parse.
 	* @param resultSet The ResultSet this date is part of.
@@ -881,6 +888,13 @@ public abstract class AbstractJdbc1ResultSet
 			rs.sbuf.append(s);
 			int slen = s.length();
 
+			// For a Timestamp, the fractional seconds are stored in the
+			// nanos field. As a DateFormat is used for parsing which can
+			// only parse to millisecond precision and which returns a
+			// Date object, the fractional second parsing is completely
+			// separate.
+			int nanos = 0;
+
 			if (slen > 19)
 			{
 				// The len of the ISO string to the second value is 19 chars. If
@@ -894,25 +908,36 @@ public abstract class AbstractJdbc1ResultSet
 				char c = s.charAt(i++);
 				if (c == '.')
 				{
-					// Found a fractional value. Append up to 3 digits including
-					// the leading '.'
-					do
+					// Found a fractional value.
+					final int start = i;
+					while (true)
 					{
-						if (i < 24)
-							rs.sbuf.append(c);
 						c = s.charAt(i++);
+						if (!Character.isDigit(c))
+							break;
+						if (i == slen)
+							{
+								i++;
+								break;
+							}
 					}
-					while (i < slen && Character.isDigit(c));
 
-					// If there wasn't at least 3 digits we should add some zeros
-					// to make up the 3 digits we tell java to expect.
-					for (int j = i; j < 24; j++)
-						rs.sbuf.append('0');
-				}
-				else
-				{
-					// No fractional seconds, lets add some.
-					rs.sbuf.append(".000");
+					// The range [start, i - 1) contains all fractional digits.
+					final int end = i - 1;
+					try
+						{
+							nanos = Integer.parseInt(s.substring(start, end));
+						}
+					catch (NumberFormatException e)
+						{
+							throw new PSQLException("postgresql.unusual", e);
+						}
+
+					// The nanos field stores nanoseconds. Adjust the parsed
+					// value to the correct magnitude.
+					for (int digitsToNano = 9 - (end - start);
+						 digitsToNano > 0; --digitsToNano)
+						nanos *= 10;
 				}
 
 				if (i < slen)
@@ -929,7 +954,7 @@ public abstract class AbstractJdbc1ResultSet
 						rs.sbuf.append(":00");
 
 					// we'll use this dateformat string to parse the result.
-					df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
+					df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
 				}
 				else
 				{
@@ -938,11 +963,11 @@ public abstract class AbstractJdbc1ResultSet
 					if (pgDataType.equals("timestamptz"))
 					{
 						rs.sbuf.append(" GMT");
-						df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
+						df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
 					}
 					else
 					{
-						df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+						df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 					}
 				}
 			}
@@ -981,9 +1006,13 @@ public abstract class AbstractJdbc1ResultSet
 			{
 				// All that's left is to parse the string and return the ts.
 				if ( org.postgresql.Driver.logDebug )
-					org.postgresql.Driver.debug( "" + df.parse(rs.sbuf.toString()).getTime() );
+					org.postgresql.Driver.debug("the data after parsing is " 
+                     + rs.sbuf.toString() + " with " + nanos + " nanos");
 
-				return new Timestamp(df.parse(rs.sbuf.toString()).getTime());
+				Timestamp result = 
+					new Timestamp(df.parse(rs.sbuf.toString()).getTime());
+				result.setNanos(nanos);
+				return result;
 			}
 			catch (ParseException e)
 			{
diff --git a/org/postgresql/test/jdbc2/TimestampTest.java b/org/postgresql/test/jdbc2/TimestampTest.java
index c859ffb..cb60101 100644
--- a/org/postgresql/test/jdbc2/TimestampTest.java
+++ b/org/postgresql/test/jdbc2/TimestampTest.java
@@ -52,11 +52,12 @@ public class TimestampTest extends TestCase
 			assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE, "'" + TS1WTZ_PGFORMAT + "'")));
 			assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE, "'" + TS2WTZ_PGFORMAT + "'")));
 			assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE, "'" + TS3WTZ_PGFORMAT + "'")));
+			assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE, "'" + TS4WTZ_PGFORMAT + "'")));
 
 			// Fall through helper
 			timestampTestWTZ();
 
-			assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE));
+			assertEquals(4, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE));
 
 			stmt.close();
 		}
@@ -88,10 +89,13 @@ public class TimestampTest extends TestCase
 			pstmt.setTimestamp(1, TS3WTZ);
 			assertEquals(1, pstmt.executeUpdate());
 
+			pstmt.setTimestamp(1, TS4WTZ);
+			assertEquals(1, pstmt.executeUpdate());
+
 			// Fall through helper
 			timestampTestWTZ();
 
-			assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE));
+			assertEquals(4, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE));
 
 			pstmt.close();
 			stmt.close();
@@ -117,11 +121,12 @@ public class TimestampTest extends TestCase
 			assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE, "'" + TS1WOTZ_PGFORMAT + "'")));
 			assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE, "'" + TS2WOTZ_PGFORMAT + "'")));
 			assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE, "'" + TS3WOTZ_PGFORMAT + "'")));
+			assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE, "'" + TS4WOTZ_PGFORMAT + "'")));
 
 			// Fall through helper
 			timestampTestWOTZ();
 
-			assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));
+			assertEquals(4, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));
 
 			stmt.close();
 		}
@@ -154,10 +159,13 @@ public class TimestampTest extends TestCase
 			pstmt.setTimestamp(1, TS3WOTZ);
 			assertEquals(1, pstmt.executeUpdate());
 
+			pstmt.setTimestamp(1, TS4WOTZ);
+			assertEquals(1, pstmt.executeUpdate());
+
 			// Fall through helper
 			timestampTestWOTZ();
 
-			assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));
+			assertEquals(4, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));
 
 			pstmt.close();
 			stmt.close();
@@ -195,6 +203,11 @@ public class TimestampTest extends TestCase
 		assertNotNull(t);
 		assertTrue(t.equals(TS3WTZ));
 
+		assertTrue(rs.next());
+		t = rs.getTimestamp(1);
+		assertNotNull(t);
+		assertTrue(t.equals(TS4WTZ));
+
 		assertTrue(! rs.next()); // end of table. Fail if more entries exist.
 
 		rs.close();
@@ -216,17 +229,22 @@ public class TimestampTest extends TestCase
 		assertTrue(rs.next());
 		t = rs.getTimestamp(1);
 		assertNotNull(t);
-		assertTrue(t.toString().equals(TS1WOTZ_JAVAFORMAT));
+		assertTrue(t.equals(TS1WOTZ));
 
 		assertTrue(rs.next());
 		t = rs.getTimestamp(1);
 		assertNotNull(t);
-		assertTrue(t.toString().equals(TS2WOTZ_JAVAFORMAT));
+		assertTrue(t.equals(TS2WOTZ));
 
 		assertTrue(rs.next());
 		t = rs.getTimestamp(1);
 		assertNotNull(t);
-		assertTrue(t.toString().equals(TS3WOTZ_JAVAFORMAT));
+		assertTrue(t.equals(TS3WOTZ));
+
+		assertTrue(rs.next());
+		t = rs.getTimestamp(1);
+		assertNotNull(t);
+		assertTrue(t.equals(TS4WOTZ));
 
 		assertTrue(! rs.next()); // end of table. Fail if more entries exist.
 
@@ -277,20 +295,21 @@ public class TimestampTest extends TestCase
 	private static final java.sql.Timestamp TS3WTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123000000, "GMT");
 	private static final String TS3WTZ_PGFORMAT = "2000-07-07 15:00:00.123+00";
 
+	private static final java.sql.Timestamp TS4WTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123456000, "GMT");
+	private static final String TS4WTZ_PGFORMAT = "2000-07-07 15:00:00.123456+00";
+
 
 	private static final java.sql.Timestamp TS1WOTZ = getTimestamp(1950, 2, 7, 15, 0, 0, 100000000, null);
 	private static final String TS1WOTZ_PGFORMAT = "1950-02-07 15:00:00.1";
-	private static final String TS1WOTZ_JAVAFORMAT = "1950-02-07 15:00:00.1";
 
 	private static final java.sql.Timestamp TS2WOTZ = getTimestamp(2000, 2, 7, 15, 0, 0, 120000000, null);
 	private static final String TS2WOTZ_PGFORMAT = "2000-02-07 15:00:00.12";
-	//there is probably a bug here in that this needs to be .1 instead of .12, but I couldn't find it now
-	private static final String TS2WOTZ_JAVAFORMAT = "2000-02-07 15:00:00.1";
 
 	private static final java.sql.Timestamp TS3WOTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123000000, null);
 	private static final String TS3WOTZ_PGFORMAT = "2000-07-07 15:00:00.123";
-	//there is probably a bug here in that this needs to be .12 instead of .123, but I couldn't find it now
-	private static final String TS3WOTZ_JAVAFORMAT = "2000-07-07 15:00:00.12";
+
+	private static final java.sql.Timestamp TS4WOTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123456000, null);
+	private static final String TS4WOTZ_PGFORMAT = "2000-07-07 15:00:00.123456";
 
 	private static final String TSWTZ_TABLE = "testtimestampwtz";
 	private static final String TSWOTZ_TABLE = "testtimestampwotz";

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libpostgresql-jdbc-java.git



More information about the pkg-java-commits mailing list