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",
|
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"),
|
"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.
|
* Use binary format for sending and receiving data if possible.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -29,6 +29,12 @@ public interface BaseConnection extends PGConnection, Connection {
|
|||||||
*/
|
*/
|
||||||
ClientLogic getClientLogic();
|
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.
|
* 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.Logger;
|
||||||
import org.postgresql.log.Log;
|
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>
|
* <p>Helper class to handle boolean type of PostgreSQL.</p>
|
||||||
@ -21,6 +25,8 @@ import org.postgresql.log.Log;
|
|||||||
class BooleanTypeUtil {
|
class BooleanTypeUtil {
|
||||||
|
|
||||||
private static Log LOGGER = Logger.getLogger(BooleanTypeUtil.class.getName());
|
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() {
|
private BooleanTypeUtil() {
|
||||||
}
|
}
|
||||||
@ -54,19 +60,24 @@ class BooleanTypeUtil {
|
|||||||
private static boolean fromString(final String strval) throws PSQLException {
|
private static boolean fromString(final String strval) throws PSQLException {
|
||||||
// Leading or trailing whitespace is ignored, and case does not matter.
|
// Leading or trailing whitespace is ignored, and case does not matter.
|
||||||
final String val = strval.trim();
|
final String val = strval.trim();
|
||||||
if ("1".equals(val) || "true".equalsIgnoreCase(val)
|
if (isTrueStr(val)) {
|
||||||
|| "t".equalsIgnoreCase(val) || "yes".equalsIgnoreCase(val)
|
|
||||||
|| "y".equalsIgnoreCase(val) || "on".equalsIgnoreCase(val)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ("0".equals(val) || "false".equalsIgnoreCase(val)
|
if (isFalseStr(val)) {
|
||||||
|| "f".equalsIgnoreCase(val) || "no".equalsIgnoreCase(val)
|
|
||||||
|| "n".equalsIgnoreCase(val) || "off".equalsIgnoreCase(val)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
throw cannotCoerceException(strval);
|
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 {
|
private static boolean fromCharacter(final Character charval) throws PSQLException {
|
||||||
if ('1' == charval || 't' == charval || 'T' == charval
|
if ('1' == charval || 't' == charval || 'T' == charval
|
||||||
|| 'y' == charval || 'Y' == charval) {
|
|| 'y' == charval || 'Y' == charval) {
|
||||||
|
|||||||
@ -77,10 +77,7 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URISyntaxException;
|
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.PGClob;
|
||||||
import org.postgresql.core.types.PGBlob;
|
import org.postgresql.core.types.PGBlob;
|
||||||
|
|
||||||
@ -166,6 +163,9 @@ public class PgConnection implements BaseConnection {
|
|||||||
// Current warnings; there might be more on queryExecutor too.
|
// Current warnings; there might be more on queryExecutor too.
|
||||||
private SQLWarning firstWarning = null;
|
private SQLWarning firstWarning = null;
|
||||||
|
|
||||||
|
// True if bit to string else bit to boolean.
|
||||||
|
private boolean bitToString = false;
|
||||||
|
|
||||||
// Timer for scheduling TimerTasks for this connection.
|
// Timer for scheduling TimerTasks for this connection.
|
||||||
// Only instantiated if a task is actually scheduled.
|
// Only instantiated if a task is actually scheduled.
|
||||||
private volatile Timer cancelTimer = null;
|
private volatile Timer cancelTimer = null;
|
||||||
@ -244,6 +244,7 @@ public class PgConnection implements BaseConnection {
|
|||||||
|
|
||||||
this.creatingURL = url;
|
this.creatingURL = url;
|
||||||
|
|
||||||
|
bitToString = PGProperty.BIT_TO_STRING.getBoolean(info);
|
||||||
setDefaultFetchSize(PGProperty.DEFAULT_ROW_FETCH_SIZE.getInt(info));
|
setDefaultFetchSize(PGProperty.DEFAULT_ROW_FETCH_SIZE.getInt(info));
|
||||||
|
|
||||||
setPrepareThreshold(PGProperty.PREPARE_THRESHOLD.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() {
|
public int getPrepareThreshold() {
|
||||||
return prepareThreshold;
|
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 {
|
public void setByte(int parameterIndex, byte x) throws SQLException {
|
||||||
setShort(parameterIndex, x);
|
setShort(parameterIndex, x);
|
||||||
}
|
}
|
||||||
@ -632,9 +637,11 @@ class PgPreparedStatement extends PgStatement implements PreparedStatement {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Types.BOOLEAN:
|
case Types.BOOLEAN:
|
||||||
case Types.BIT:
|
|
||||||
setBoolean(parameterIndex, BooleanTypeUtil.castToBoolean(in));
|
setBoolean(parameterIndex, BooleanTypeUtil.castToBoolean(in));
|
||||||
break;
|
break;
|
||||||
|
case Types.BIT:
|
||||||
|
setBit(parameterIndex, BooleanTypeUtil.castToBoolean(in));
|
||||||
|
break;
|
||||||
case Types.BINARY:
|
case Types.BINARY:
|
||||||
case Types.VARBINARY:
|
case Types.VARBINARY:
|
||||||
case Types.LONGVARBINARY:
|
case Types.LONGVARBINARY:
|
||||||
|
|||||||
@ -27,8 +27,6 @@ import org.postgresql.util.PGobject;
|
|||||||
import org.postgresql.util.PGtokenizer;
|
import org.postgresql.util.PGtokenizer;
|
||||||
import org.postgresql.util.PSQLException;
|
import org.postgresql.util.PSQLException;
|
||||||
import org.postgresql.util.PSQLState;
|
import org.postgresql.util.PSQLState;
|
||||||
import org.postgresql.log.Logger;
|
|
||||||
import org.postgresql.log.Log;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.CharArrayReader;
|
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 {
|
protected Object internalGetObject(int columnIndex, Field field) throws SQLException {
|
||||||
switch (getSQLType(columnIndex)) {
|
switch (getSQLType(columnIndex)) {
|
||||||
case Types.BOOLEAN:
|
case Types.BOOLEAN:
|
||||||
case Types.BIT:
|
|
||||||
return getBoolean(columnIndex);
|
return getBoolean(columnIndex);
|
||||||
|
case Types.BIT:
|
||||||
|
return getBit(columnIndex);
|
||||||
case Types.SQLXML:
|
case Types.SQLXML:
|
||||||
return getSQLXML(columnIndex);
|
return getSQLXML(columnIndex);
|
||||||
case Types.TINYINT:
|
case Types.TINYINT:
|
||||||
@ -2093,6 +2092,20 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS
|
|||||||
return BooleanTypeUtil.castToBoolean(getString(columnIndex));
|
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 BYTEMAX = new BigInteger(Byte.toString(Byte.MAX_VALUE));
|
||||||
private static final BigInteger BYTEMIN = new BigInteger(Byte.toString(Byte.MIN_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