Permalink
Browse files

fix: robust castToBoolean for setObject in PreparedStatement (#714)

  • Loading branch information...
jorsol authored and davecramer committed Dec 14, 2016
1 parent 436365b commit edc2a14af8837911a48bb322363bb8b70d2b173d
@@ -283,7 +283,8 @@ public void setNull(int parameterIndex, int sqlType) throws SQLException {
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
checkClosed();
bindString(parameterIndex, x ? "1" : "0", Oid.BOOL);
// The key words TRUE and FALSE are the preferred (SQL-compliant) usage.
bindLiteral(parameterIndex, x ? "TRUE" : "FALSE", Oid.BOOL);
}
public void setByte(int parameterIndex, byte x) throws SQLException {
@@ -877,37 +878,73 @@ private static BigDecimal castToBigDecimal(final Object in, final int scale) thr
}
private static boolean castToBoolean(final Object in) throws SQLException {
try {
if (in instanceof String) {
return ((String) in).equalsIgnoreCase("true") || ((String) in).equals("1")
|| ((String) in).equalsIgnoreCase("t");
}
if (in instanceof BigDecimal) {
return ((BigDecimal) in).signum() != 0;
}
if (in instanceof Number) {
return ((Number) in).longValue() != 0L;
}
if (in instanceof java.util.Date) {
return ((java.util.Date) in).getTime() != 0L;
}
if (in instanceof Boolean) {
return (Boolean) in;
if (in instanceof Boolean) {
return (Boolean) in;
}
if (in instanceof String) {
// Leading or trailing whitespace is ignored, and case does not matter.
final String strval = ((String) in).trim();
Boolean value = booleanTypeFromString(strval);
if (value == null) {
throw cannotCastException("String", "boolean");
}
if (in instanceof Clob) {
final String asString = asString((Clob) in);
return asString.equalsIgnoreCase("true") || asString.equals("1")
|| asString.equalsIgnoreCase("t");
return value;
}
if (in instanceof Character) {
Boolean value = null;
final Character charval = (Character) in;
if ('1' == charval || 't' == charval || 'T' == charval
|| 'y' == charval || 'Y' == charval) {
value = Boolean.TRUE;
} else if ('0' == charval || 'f' == charval || 'F' == charval
|| 'n' == charval || 'N' == charval) {
value = Boolean.FALSE;
} else if (value == null) {
throw cannotCastException("Character", "boolean");
}
if (in instanceof Character) {
return (Character) in == '1' || (Character) in == 't' || (Character) in == 'T';
return value;
}
if (in instanceof BigDecimal) {
return ((BigDecimal) in).signum() != 0;
}
if (in instanceof Number) {
return ((Number) in).longValue() != 0L;
}
if (in instanceof java.util.Date) {
return ((java.util.Date) in).getTime() != 0L;
}
if (in instanceof Clob) {
final String strval = asString((Clob) in).trim();
Boolean value = booleanTypeFromString(strval);
if (value == null) {
throw cannotCastException("Clob", "boolean");
}
} catch (final Exception e) {
throw cannotCastException(in.getClass().getName(), "boolean", e);
return value;
}
throw cannotCastException(in.getClass().getName(), "boolean");
}
/**
* Based on values accepted by the PostgreSQL server:
* https://www.postgresql.org/docs/current/static/datatype-boolean.html
*
* @param val String with the value to "parse"
* @return Boolean if any valid value match, null otherwise.
*/
private static Boolean booleanTypeFromString(final String val) {
if ("1".equals(val) || "true".equalsIgnoreCase(val)
|| "t".equalsIgnoreCase(val) || "yes".equalsIgnoreCase(val)
|| "y".equalsIgnoreCase(val) || "on".equalsIgnoreCase(val)) {
return Boolean.TRUE;
}
if ("0".equals(val) || "false".equalsIgnoreCase(val)
|| "f".equalsIgnoreCase(val) || "no".equalsIgnoreCase(val)
|| "n".equalsIgnoreCase(val) || "off".equalsIgnoreCase(val)) {
return Boolean.FALSE;
}
return null;
}
private static String castToString(final Object in) throws SQLException {
try {
if (in instanceof String) {
@@ -21,6 +21,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
@@ -512,28 +513,101 @@ public void testFloat() throws SQLException {
@Test
public void testBoolean() throws SQLException {
PreparedStatement pstmt = con.prepareStatement(
"CREATE TEMP TABLE bool_tab (max_val boolean, min_val boolean, null_val boolean)");
"CREATE TEMP TABLE bool_tab (bool_val boolean, null_val boolean, tf_val boolean, "
+ "truefalse_val boolean, yn_val boolean, yesno_val boolean, onoff_val boolean, onezero_val boolean)");
pstmt.executeUpdate();
pstmt.close();
pstmt = con.prepareStatement("insert into bool_tab values (?,?,?)");
pstmt = con.prepareStatement("insert into bool_tab values (?,?,?,?,?,?,?,?)");
// Test TRUE values
pstmt.setBoolean(1, true);
pstmt.setBoolean(2, false);
pstmt.setNull(3, Types.BIT);
pstmt.executeUpdate();
pstmt.close();
pstmt.setObject(1, Boolean.TRUE);
pstmt.setNull(2, Types.BIT);
pstmt.setObject(3, 't', Types.BIT);
pstmt.setObject(3, 'T', Types.BIT);
pstmt.setObject(3, "t", Types.BIT);
pstmt.setObject(4, "true", Types.BIT);
pstmt.setObject(5, 'y', Types.BIT);
pstmt.setObject(5, 'Y', Types.BIT);
pstmt.setObject(5, "Y", Types.BIT);
pstmt.setObject(6, "YES", Types.BIT);
pstmt.setObject(7, "On", Types.BIT);
pstmt.setObject(8, '1', Types.BIT);
pstmt.setObject(8, "1", Types.BIT);
assertEquals("one row inserted, true values", 1, pstmt.executeUpdate());
// Test FALSE values
pstmt.setBoolean(1, false);
pstmt.setObject(1, Boolean.FALSE);
pstmt.setNull(2, Types.BOOLEAN);
pstmt.setObject(3, 'f', Types.BOOLEAN);
pstmt.setObject(3, 'F', Types.BOOLEAN);
pstmt.setObject(3, "F", Types.BOOLEAN);
pstmt.setObject(4, "false", Types.BOOLEAN);
pstmt.setObject(5, 'n', Types.BOOLEAN);
pstmt.setObject(5, 'N', Types.BOOLEAN);
pstmt.setObject(5, "N", Types.BOOLEAN);
pstmt.setObject(6, "NO", Types.BOOLEAN);
pstmt.setObject(7, "Off", Types.BOOLEAN);
pstmt.setObject(8, "0", Types.BOOLEAN);
pstmt.setObject(8, '0', Types.BOOLEAN);
assertEquals("one row inserted, false values", 1, pstmt.executeUpdate());
// Test weird values
pstmt.setObject(1, new java.util.Date(0), Types.BOOLEAN);
pstmt.setObject(2, BigDecimal.ONE, Types.BOOLEAN);
pstmt.setObject(3, 0L, Types.BOOLEAN);
pstmt.setObject(4, 0x1, Types.BOOLEAN);
pstmt.setObject(5, 0, Types.BOOLEAN);
pstmt.setObject(6, Integer.valueOf("1"), Types.BOOLEAN);
pstmt.clearParameters();
try {
pstmt.setObject(1, "this is not boolean", Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(e.getMessage(), "Cannot convert an instance of String to type boolean");
}
try {
pstmt.setObject(1, 'X', Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(e.getMessage(), "Cannot convert an instance of Character to type boolean");
}
try {
File obj = new File("");
pstmt.setObject(1, obj, Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(e.getMessage(), "Cannot convert an instance of java.io.File to type boolean");
}
pstmt.close();
pstmt = con.prepareStatement("select * from bool_tab");
ResultSet rs = pstmt.executeQuery();
assertTrue(rs.next());
assertTrue("expected true, received " + rs.getBoolean(1), rs.getBoolean(1));
rs.getFloat(2);
assertTrue(rs.wasNull());
assertTrue("expected true, received " + rs.getBoolean(3), rs.getBoolean(3));
assertTrue("expected true, received " + rs.getBoolean(4), rs.getBoolean(4));
assertTrue("expected true, received " + rs.getBoolean(5), rs.getBoolean(5));
assertTrue("expected true, received " + rs.getBoolean(6), rs.getBoolean(6));
assertTrue("expected true, received " + rs.getBoolean(7), rs.getBoolean(7));
assertTrue("expected true, received " + rs.getBoolean(8), rs.getBoolean(8));
assertTrue("expected true,received " + rs.getBoolean(1), rs.getBoolean(1));
assertFalse("expected false,received " + rs.getBoolean(2), rs.getBoolean(2));
rs.getFloat(3);
assertTrue(rs.next());
assertFalse("expected false, received " + rs.getBoolean(1), rs.getBoolean(1));
rs.getBoolean(2);
assertTrue(rs.wasNull());
assertFalse("expected false, received " + rs.getBoolean(3), rs.getBoolean(3));
assertFalse("expected false, received " + rs.getBoolean(4), rs.getBoolean(4));
assertFalse("expected false, received " + rs.getBoolean(5), rs.getBoolean(5));
assertFalse("expected false, received " + rs.getBoolean(6), rs.getBoolean(6));
assertFalse("expected false, received " + rs.getBoolean(7), rs.getBoolean(7));
assertFalse("expected false, received " + rs.getBoolean(8), rs.getBoolean(8));
rs.close();
pstmt.close();
}
@Test

0 comments on commit edc2a14

Please sign in to comment.