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]