postgresql-jdbc.git / summary / log / commit / refs

commit    e38868b29cafa7e8a9a5db67adb5a67cc2b5f230
Author:   Svein Baardsen <svein.baardsen@gmail.com>
Commit:   Dave Cramer <davecramer@gmail.com>
Date:     Tue Jan 28 15:54:19 2020 +0000

    fix: #1677 NumberFormatException when fetching PGInterval with small value (#1678)
    
    * fix: #1677 NumberFormatException when fetching PGInterval with small value
    
    * fix: PGInterval.getValue for microsecond values
    
    * ensure getValue always uses at least one decimal place for seconds
    
    * fix: PGInterval.getSeconds for microsecond values


.../main/java/org/postgresql/util/PGInterval.java | 49 ++++++++-------------- .../org/postgresql/test/jdbc2/IntervalTest.java | 45 ++++++++++++++++++++ 2 files changed, 63 insertions(+), 31 deletions(-) diff --git a/pgjdbc/src/main/java/org/postgresql/util/PGInterval.java b/pgjdbc/src/main/java/org/postgresql/util/PGInterval.java index 439300d8..b03bc6b9 100644 --- a/pgjdbc/src/main/java/org/postgresql/util/PGInterval.java +++ b/pgjdbc/src/main/java/org/postgresql/util/PGInterval.java @@ -7,15 +7,20 @@ package org.postgresql.util; import java.io.Serializable; import java.sql.SQLException; +import java.text.DecimalFormat; import java.util.Calendar; import java.util.Date; +import java.util.Locale; import java.util.StringTokenizer; +import java.util.concurrent.TimeUnit; /** * This implements a class that handles the PostgreSQL interval type. */ public class PGInterval extends PGobject implements Serializable, Cloneable { + private static final int MICROS_IN_SECOND = 1000000; + private int years; private int months; private int days; @@ -239,12 +244,16 @@ public class PGInterval extends PGobject implements Serializable, Cloneable { * @return String represented interval */ public String getValue() { - return years + " years " - + months + " mons " - + days + " days " - + hours + " hours " - + minutes + " mins " - + wholeSeconds + '.' + microSeconds + " secs"; + return String.format( + Locale.ROOT, + "%d years %d mons %d days %d hours %d mins %s secs", + years, + months, + days, + hours, + minutes, + new DecimalFormat("0.0#####").format(getSeconds()) + ); } /** @@ -343,14 +352,7 @@ public class PGInterval extends PGobject implements Serializable, Cloneable { * @return seconds represented by this interval */ public double getSeconds() { - if ( microSeconds < 0) { - if ( wholeSeconds == 0 ) { - return Double.parseDouble("-0." + -microSeconds); - } else { - return Double.parseDouble("" + wholeSeconds + '.' + -microSeconds); - } - } - return Double.parseDouble("" + wholeSeconds + '.' + microSeconds ); + return wholeSeconds + (double) microSeconds / MICROS_IN_SECOND; } public int getWholeSeconds() { @@ -367,23 +369,8 @@ public class PGInterval extends PGobject implements Serializable, Cloneable { * @param seconds seconds to set */ public void setSeconds(double seconds) { - String str = Double.toString(seconds); - int decimal = str.indexOf('.'); - if (decimal > 0) { - - /* how many 10's do we need to multiply by to get microseconds */ - String micSeconds = str.substring(decimal + 1); - int power = 6 - micSeconds.length(); - - microSeconds = Integer.parseInt(micSeconds) * (int)Math.pow(10,power); - wholeSeconds = Integer.parseInt(str.substring(0,decimal)); - } else { - microSeconds = 0; - wholeSeconds = Integer.parseInt(str); - } - if ( seconds < 0 ) { - microSeconds = -microSeconds; - } + wholeSeconds = (int) seconds; + microSeconds = (int) Math.round((seconds - wholeSeconds) * MICROS_IN_SECOND); } /** diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/IntervalTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/IntervalTest.java index 73517478..13e3a794 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/IntervalTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/IntervalTest.java @@ -305,6 +305,51 @@ public class IntervalTest { assertEquals(-4, pgi.getHours()); } + @Test + public void testSmallValue() throws SQLException { + PreparedStatement pstmt = conn.prepareStatement("INSERT INTO testinterval VALUES (?)"); + pstmt.setObject(1, new PGInterval("0.0001 seconds")); + pstmt.executeUpdate(); + pstmt.close(); + + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT v FROM testinterval"); + assertTrue(rs.next()); + PGInterval pgi = (PGInterval) rs.getObject(1); + assertEquals(0, pgi.getYears()); + assertEquals(0, pgi.getMonths()); + assertEquals(0, pgi.getDays()); + assertEquals(0, pgi.getHours()); + assertEquals(0, pgi.getMinutes()); + assertEquals(0, pgi.getWholeSeconds()); + assertEquals(100, pgi.getMicroSeconds()); + assertFalse(rs.next()); + rs.close(); + stmt.close(); + } + + @Test + public void testGetValueForSmallValue() throws SQLException { + PGInterval orig = new PGInterval("0.0001 seconds"); + PGInterval copy = new PGInterval(orig.getValue()); + + assertEquals(orig, copy); + } + + @Test + public void testGetSecondsForSmallValue() throws SQLException { + PGInterval pgi = new PGInterval("0.000001 seconds"); + + assertEquals(0.000001, pgi.getSeconds(), 0.000000001); + } + + @Test + public void testMicroSecondsAreRoundedToNearest() throws SQLException { + PGInterval pgi = new PGInterval("0.0000007 seconds"); + + assertEquals(1, pgi.getMicroSeconds()); + } + private java.sql.Date makeDate(int y, int m, int d) { return new java.sql.Date(y - 1900, m - 1, d); } [parent: 3dd5dff2b095]