Skip to content

Commit 8880c33

Browse files
InitFlogotson
andauthored
fix: avoid double precision in getBigDecimal
If a column has the real type affinity and the value can be represented with the limited accuracy of a double, the function safeGetColumnType(checkCol(col)) evalutes to SQLITE_FLOAT. Getting the value using safeGetDoubleCol(col) causes an implicit conversion to a double. Since version 3.43.0 the sqlite source doesn't round the value anymore, but returned the value including the 8-byte IEEE floating point number inaccuracies. Somehow different operating systems behave differently. This explains, why the test only failed on Windows. Using safeGetColumnText(col) avoids this lossy conversion. Closes: #1002 Co-authored-by: Gauthier Roebroeck <gauthier.roebroeck@gmail.com>
1 parent 4dba62c commit 8880c33

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

src/main/java/org/sqlite/jdbc3/JDBC3ResultSet.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,10 @@ public BigDecimal getBigDecimal(int col) throws SQLException {
157157
switch (safeGetColumnType(checkCol(col))) {
158158
case SQLITE_NULL:
159159
return null;
160-
case SQLITE_FLOAT:
161-
return BigDecimal.valueOf(safeGetDoubleCol(col));
162160
case SQLITE_INTEGER:
163161
return BigDecimal.valueOf(safeGetLongCol(col));
162+
case SQLITE_FLOAT:
163+
// avoid double precision
164164
default:
165165
final String stringValue = safeGetColumnText(col);
166166
try {

src/test/java/org/sqlite/PrepStmtTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import static org.assertj.core.data.Offset.offset;
88

99
import java.io.ByteArrayInputStream;
10+
import java.math.BigDecimal;
1011
import java.nio.charset.StandardCharsets;
1112
import java.sql.Connection;
1213
import java.sql.Date;
@@ -830,4 +831,46 @@ public void gh914_reuseExecute() throws SQLException {
830831
assertThat(rs2).isNotNull();
831832
}
832833
}
834+
835+
@Test
836+
public void gh1002_pi() throws SQLException {
837+
BigDecimal pi = new BigDecimal("3.14");
838+
stat.executeUpdate("create table gh1002(nr number(10,2))");
839+
840+
try (PreparedStatement ps = conn.prepareStatement("insert into gh1002 values (?)")) {
841+
ps.setBigDecimal(1, pi);
842+
ps.execute();
843+
}
844+
845+
ResultSet rs = stat.executeQuery("select nr from gh1002");
846+
assertThat(rs.getBigDecimal(1)).isEqualTo(pi);
847+
}
848+
849+
@Test
850+
public void gh1002_pi_real() throws SQLException {
851+
BigDecimal pi = new BigDecimal("3.14");
852+
stat.executeUpdate("create table gh1002(nr REAL)");
853+
854+
try (PreparedStatement ps = conn.prepareStatement("insert into gh1002 values (?)")) {
855+
ps.setBigDecimal(1, pi);
856+
ps.execute();
857+
}
858+
859+
ResultSet rs = stat.executeQuery("select nr from gh1002");
860+
assertThat(rs.getBigDecimal(1)).isEqualTo(pi);
861+
}
862+
863+
@Test
864+
public void gh1002_pi_text() throws SQLException {
865+
BigDecimal pi = new BigDecimal("3.14");
866+
stat.executeUpdate("create table gh1002(nr TEXT)");
867+
868+
try (PreparedStatement ps = conn.prepareStatement("insert into gh1002 values (?)")) {
869+
ps.setBigDecimal(1, pi);
870+
ps.execute();
871+
}
872+
873+
ResultSet rs = stat.executeQuery("select nr from gh1002");
874+
assertThat(rs.getBigDecimal(1)).isEqualTo(pi);
875+
}
833876
}

0 commit comments

Comments
 (0)