add bitToString info property to solve bit type use issue
This commit is contained in:
@ -128,6 +128,12 @@ public enum PGProperty {
|
||||
DEFAULT_ROW_FETCH_SIZE("defaultRowFetchSize", "0",
|
||||
"Positive number of rows that should be fetched from the database when more rows are needed for ResultSet by each fetch iteration"),
|
||||
|
||||
/**
|
||||
* Use binary format for sending and receiving data if possible.
|
||||
*/
|
||||
BIT_TO_STRING("bitToString", "false",
|
||||
"Auto Convert bit or bit(n) to String type in ResultSet.getObject"),
|
||||
|
||||
/**
|
||||
* Use binary format for sending and receiving data if possible.
|
||||
*/
|
||||
|
||||
@ -29,6 +29,12 @@ public interface BaseConnection extends PGConnection, Connection {
|
||||
*/
|
||||
ClientLogic getClientLogic();
|
||||
|
||||
/**
|
||||
* True if bit convert to string type else to boolean type, default is false.
|
||||
* @return
|
||||
*/
|
||||
boolean getBitToString();
|
||||
|
||||
/**
|
||||
* Cancel the current query executing on this connection.
|
||||
*
|
||||
|
||||
@ -11,6 +11,10 @@ import org.postgresql.util.PSQLState;
|
||||
import org.postgresql.log.Logger;
|
||||
import org.postgresql.log.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Helper class to handle boolean type of PostgreSQL.</p>
|
||||
@ -21,6 +25,8 @@ import org.postgresql.log.Log;
|
||||
class BooleanTypeUtil {
|
||||
|
||||
private static Log LOGGER = Logger.getLogger(BooleanTypeUtil.class.getName());
|
||||
private static final Set<String> TRUE_SETS = Arrays.stream(new String[]{"1", "true", "t", "yes", "y", "on"}).collect(Collectors.toSet());
|
||||
private static final Set<String> FALSE_SETS = Arrays.stream(new String[]{"0", "false", "f", "no", "n", "off"}).collect(Collectors.toSet());
|
||||
|
||||
private BooleanTypeUtil() {
|
||||
}
|
||||
@ -54,19 +60,24 @@ class BooleanTypeUtil {
|
||||
private static boolean fromString(final String strval) throws PSQLException {
|
||||
// Leading or trailing whitespace is ignored, and case does not matter.
|
||||
final String val = strval.trim();
|
||||
if ("1".equals(val) || "true".equalsIgnoreCase(val)
|
||||
|| "t".equalsIgnoreCase(val) || "yes".equalsIgnoreCase(val)
|
||||
|| "y".equalsIgnoreCase(val) || "on".equalsIgnoreCase(val)) {
|
||||
if (isTrueStr(val)) {
|
||||
return true;
|
||||
}
|
||||
if ("0".equals(val) || "false".equalsIgnoreCase(val)
|
||||
|| "f".equalsIgnoreCase(val) || "no".equalsIgnoreCase(val)
|
||||
|| "n".equalsIgnoreCase(val) || "off".equalsIgnoreCase(val)) {
|
||||
if (isFalseStr(val)) {
|
||||
return false;
|
||||
}
|
||||
throw cannotCoerceException(strval);
|
||||
}
|
||||
|
||||
private static boolean isTrueStr(final String strval) {
|
||||
return TRUE_SETS.contains(strval.toLowerCase());
|
||||
}
|
||||
|
||||
private static boolean isFalseStr(final String strval) {
|
||||
return FALSE_SETS.contains(strval.toLowerCase());
|
||||
}
|
||||
|
||||
|
||||
private static boolean fromCharacter(final Character charval) throws PSQLException {
|
||||
if ('1' == charval || 't' == charval || 'T' == charval
|
||||
|| 'y' == charval || 'Y' == charval) {
|
||||
|
||||
@ -77,10 +77,7 @@ import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
import org.postgresql.core.types.PGClob;
|
||||
import org.postgresql.core.types.PGBlob;
|
||||
|
||||
@ -166,6 +163,9 @@ public class PgConnection implements BaseConnection {
|
||||
// Current warnings; there might be more on queryExecutor too.
|
||||
private SQLWarning firstWarning = null;
|
||||
|
||||
// True if bit to string else bit to boolean.
|
||||
private boolean bitToString = false;
|
||||
|
||||
// Timer for scheduling TimerTasks for this connection.
|
||||
// Only instantiated if a task is actually scheduled.
|
||||
private volatile Timer cancelTimer = null;
|
||||
@ -244,6 +244,7 @@ public class PgConnection implements BaseConnection {
|
||||
|
||||
this.creatingURL = url;
|
||||
|
||||
bitToString = PGProperty.BIT_TO_STRING.getBoolean(info);
|
||||
setDefaultFetchSize(PGProperty.DEFAULT_ROW_FETCH_SIZE.getInt(info));
|
||||
|
||||
setPrepareThreshold(PGProperty.PREPARE_THRESHOLD.getInt(info));
|
||||
@ -1276,6 +1277,11 @@ public class PgConnection implements BaseConnection {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBitToString() {
|
||||
return bitToString;
|
||||
}
|
||||
|
||||
public int getPrepareThreshold() {
|
||||
return prepareThreshold;
|
||||
}
|
||||
|
||||
@ -234,6 +234,11 @@ class PgPreparedStatement extends PgStatement implements PreparedStatement {
|
||||
}
|
||||
}
|
||||
|
||||
public void setBit(int parameterIndex, boolean x) throws SQLException {
|
||||
checkClosed();
|
||||
bindString(parameterIndex, x ? "1" : "0", Oid.BIT);
|
||||
}
|
||||
|
||||
public void setByte(int parameterIndex, byte x) throws SQLException {
|
||||
setShort(parameterIndex, x);
|
||||
}
|
||||
@ -632,9 +637,11 @@ class PgPreparedStatement extends PgStatement implements PreparedStatement {
|
||||
}
|
||||
break;
|
||||
case Types.BOOLEAN:
|
||||
case Types.BIT:
|
||||
setBoolean(parameterIndex, BooleanTypeUtil.castToBoolean(in));
|
||||
break;
|
||||
case Types.BIT:
|
||||
setBit(parameterIndex, BooleanTypeUtil.castToBoolean(in));
|
||||
break;
|
||||
case Types.BINARY:
|
||||
case Types.VARBINARY:
|
||||
case Types.LONGVARBINARY:
|
||||
|
||||
@ -27,8 +27,6 @@ import org.postgresql.util.PGobject;
|
||||
import org.postgresql.util.PGtokenizer;
|
||||
import org.postgresql.util.PSQLException;
|
||||
import org.postgresql.util.PSQLState;
|
||||
import org.postgresql.log.Logger;
|
||||
import org.postgresql.log.Log;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.CharArrayReader;
|
||||
@ -241,8 +239,9 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS
|
||||
protected Object internalGetObject(int columnIndex, Field field) throws SQLException {
|
||||
switch (getSQLType(columnIndex)) {
|
||||
case Types.BOOLEAN:
|
||||
case Types.BIT:
|
||||
return getBoolean(columnIndex);
|
||||
case Types.BIT:
|
||||
return getBit(columnIndex);
|
||||
case Types.SQLXML:
|
||||
return getSQLXML(columnIndex);
|
||||
case Types.TINYINT:
|
||||
@ -2093,6 +2092,20 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS
|
||||
return BooleanTypeUtil.castToBoolean(getString(columnIndex));
|
||||
}
|
||||
|
||||
public Object getBit(int columnIndex) throws SQLException {
|
||||
connection.getLogger().trace("[" + connection.getSocketAddress() + "] " + " getBit columnIndex: " + columnIndex);
|
||||
checkResultSet(columnIndex);
|
||||
if (wasNullFlag) {
|
||||
return null; // SQL NULL
|
||||
}
|
||||
|
||||
String val = getString(columnIndex);
|
||||
if (connection.getBitToString()) {
|
||||
return val;
|
||||
}
|
||||
return BooleanTypeUtil.castToBoolean(val);
|
||||
}
|
||||
|
||||
private static final BigInteger BYTEMAX = new BigInteger(Byte.toString(Byte.MAX_VALUE));
|
||||
private static final BigInteger BYTEMIN = new BigInteger(Byte.toString(Byte.MIN_VALUE));
|
||||
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2004, PostgreSQL Global Development Group
|
||||
* See the LICENSE file in the project root for more information.
|
||||
*/
|
||||
|
||||
package org.postgresql.test.jdbc2;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.postgresql.test.TestUtil;
|
||||
import org.postgresql.util.PGobject;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/*
|
||||
* ResultSet tests.
|
||||
*/
|
||||
public class ResultSetBitNTest extends BaseTest4 {
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
TestUtil.createTable(con, "test_bit", "id bit, id1 bit(1), id2 bit(10)");
|
||||
String insertOne = "insert into test_bit (id, id1, id2) values ('1', b'0', b'1111100000')";
|
||||
try (Statement stmt = con.createStatement()) {
|
||||
stmt.executeUpdate(insertOne);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws SQLException {
|
||||
TestUtil.dropTable(con, "test_bit");
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateProperties(Properties props) {
|
||||
super.updateProperties(props);
|
||||
props.setProperty("loggerLevel", "TRACE");
|
||||
props.setProperty("bitToString", "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertDirectly() throws SQLException {
|
||||
String insertSql = "insert into test_bit (id, id1, id2) values ('1', b'0', b'1111100000')";
|
||||
try (Statement st = con.createStatement()) {
|
||||
int number = st.executeUpdate(insertSql);
|
||||
assertEquals(1, number);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertByPreparedStatementObj() throws SQLException {
|
||||
String insertSql = "insert into test_bit (id, id1, id2) values (?::bit, ?::bit, ?)";
|
||||
try (PreparedStatement ps = con.prepareStatement(insertSql)) {
|
||||
ps.setObject(1, "1");
|
||||
ps.setObject(2, "0");
|
||||
PGobject pObj = new PGobject();
|
||||
pObj.setType("bit");
|
||||
pObj.setValue("1010111111");
|
||||
ps.setObject(3, pObj);
|
||||
boolean success = ps.execute();
|
||||
assertFalse(success);
|
||||
int num = ps.getUpdateCount();
|
||||
assertEquals(1, num);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertByPreparedStatementString() throws SQLException {
|
||||
String insertSql = "insert into test_bit (id, id1, id2) values (?::bit,?::bit,?)";
|
||||
try (PreparedStatement ps = con.prepareStatement(insertSql)) {
|
||||
ps.setString(1, "1");
|
||||
ps.setString(2, "0");
|
||||
PGobject pObj = new PGobject();
|
||||
pObj.setType("bit");
|
||||
pObj.setValue("1010111111");
|
||||
ps.setObject(3, pObj);
|
||||
boolean success = ps.execute();
|
||||
assertFalse(success);
|
||||
int num = ps.getUpdateCount();
|
||||
assertEquals(1, num);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectDirectly() throws SQLException {
|
||||
String sql = "select id, id1, id2 from test_bit";
|
||||
try (Statement st = con.createStatement()) {
|
||||
try (ResultSet rs = st.executeQuery(sql)) {
|
||||
assertTrue(rs.next());
|
||||
Object obj = rs.getObject(1);
|
||||
assertEquals("1", obj);
|
||||
Object obj1 = rs.getObject(2);
|
||||
assertEquals("0", obj1);
|
||||
Object obj2 = rs.getObject(3);
|
||||
assertEquals("1111100000", obj2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user