Skip to content

Commit

Permalink
fix: Add fallback to setObject(int, Object) for Number
Browse files Browse the repository at this point in the history
Add a fallback to the PgPreparedStatement.setObject(int, Object) method
which handles Number types. This allows support for BigInteger and
similar types (f.e. AtomicLong) which are not explicitly mentioned by
JDBC.

This fallback operates by invoking toString() on the Number, which is
the same method used by setBigDecimal(int, BigDecimal). Also,
setBigDecimal(int, BigDecimal) does now invoke setNumber(int, Number)
because they work the same way.

The tracking bug is #810.
  • Loading branch information
Robert Zenz committed Apr 14, 2017
1 parent 4ab5ccb commit 1759c07
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 6 deletions.
18 changes: 12 additions & 6 deletions pgjdbc/src/main/java/org/postgresql/jdbc/PgPreparedStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,7 @@ public void setDouble(int parameterIndex, double x) throws SQLException {
}

public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
checkClosed();
if (x == null) {
setNull(parameterIndex, Types.DECIMAL);
} else {
bindLiteral(parameterIndex, x.toString(), Oid.NUMERIC);
}
setNumber(parameterIndex, x);
}

public void setString(int parameterIndex, String x) throws SQLException {
Expand Down Expand Up @@ -515,6 +510,15 @@ private void setMap(int parameterIndex, Map<?, ?> x) throws SQLException {
}
}

private void setNumber(int parameterIndex, Number x) throws SQLException {
checkClosed();
if (x == null) {
setNull(parameterIndex, Types.DECIMAL);
} else {
bindLiteral(parameterIndex, x.toString(), Oid.NUMERIC);
}
}

@Override
public void setObject(int parameterIndex, Object in, int targetSqlType, int scale)
throws SQLException {
Expand Down Expand Up @@ -962,6 +966,8 @@ public void setObject(int parameterIndex, Object x) throws SQLException {
//#endif
} else if (x instanceof Map) {
setMap(parameterIndex, (Map<?, ?>) x);
} else if (x instanceof Number) {
setNumber(parameterIndex, (Number) x);
} else {
// Can't infer a type.
throw new PSQLException(GT.tr(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
Expand All @@ -35,6 +36,7 @@
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicLong;


@RunWith(Parameterized.class)
Expand Down Expand Up @@ -1092,6 +1094,66 @@ public void testSetObjectBigDecimalWithScale() throws SQLException {
pstruncate.close();
}

@Test
public void testSetObjectWithBigDecimal() throws SQLException {
TestUtil.createTempTable(con, "number_fallback",
"n1 numeric");
PreparedStatement psinsert = con.prepareStatement("insert into number_fallback values(?)");
PreparedStatement psselect = con.prepareStatement("select n1 from number_fallback");

psinsert.setObject(1, new BigDecimal("733"));
psinsert.execute();

ResultSet rs = psselect.executeQuery();
assertTrue(rs.next());
assertTrue(
"expected 733, but received " + rs.getBigDecimal(1),
new BigDecimal("733").compareTo(rs.getBigDecimal(1)) == 0);

psinsert.close();
psselect.close();
}

@Test
public void testSetObjectNumberFallbackWithBigInteger() throws SQLException {
TestUtil.createTempTable(con, "number_fallback",
"n1 numeric");
PreparedStatement psinsert = con.prepareStatement("insert into number_fallback values(?)");
PreparedStatement psselect = con.prepareStatement("select n1 from number_fallback");

psinsert.setObject(1, new BigInteger("733"));
psinsert.execute();

ResultSet rs = psselect.executeQuery();
assertTrue(rs.next());
assertTrue(
"expected 733, but received " + rs.getBigDecimal(1),
new BigDecimal("733").compareTo(rs.getBigDecimal(1)) == 0);

psinsert.close();
psselect.close();
}

@Test
public void testSetObjectNumberFallbackWithAtomicLong() throws SQLException {
TestUtil.createTempTable(con, "number_fallback",
"n1 numeric");
PreparedStatement psinsert = con.prepareStatement("insert into number_fallback values(?)");
PreparedStatement psselect = con.prepareStatement("select n1 from number_fallback");

psinsert.setObject(1, new AtomicLong(733));
psinsert.execute();

ResultSet rs = psselect.executeQuery();
assertTrue(rs.next());
assertTrue(
"expected 733, but received " + rs.getBigDecimal(1),
new BigDecimal("733").compareTo(rs.getBigDecimal(1)) == 0);

psinsert.close();
psselect.close();
}

@Test
public void testUnknownSetObject() throws SQLException {
PreparedStatement pstmt = con.prepareStatement("INSERT INTO intervaltable(i) VALUES (?)");
Expand Down

0 comments on commit 1759c07

Please sign in to comment.