diff --git a/pgjdbc/src/main/java/org/postgresql/PGProperty.java b/pgjdbc/src/main/java/org/postgresql/PGProperty.java index 3dc150e..82a1caf 100644 --- a/pgjdbc/src/main/java/org/postgresql/PGProperty.java +++ b/pgjdbc/src/main/java/org/postgresql/PGProperty.java @@ -580,6 +580,8 @@ public enum PGProperty { */ OPTIONS("options", null, "Specify 'options' connection initialization parameter."), + B_CMPT_MODE("BCmptMode", "false", "Specify 'dolphin.b_compatibility_mode'" + + " connection initialization parameter."), ; private String _name; diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java index c46aa70..cfefefd 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java @@ -195,6 +195,7 @@ public class PgConnection implements BaseConnection { private PGXmlFactoryFactory xmlFactoryFactory; private String socketAddress; private boolean adaptiveSetSQLType = false; + private boolean isDolphinCmpt = false; final CachedQuery borrowQuery(String sql) throws SQLException { return queryExecutor.borrowQuery(sql); } @@ -458,6 +459,9 @@ public class PgConnection implements BaseConnection { batchInsert = false; } + /* set dolphin.b_compatibility_mode to the value of PGProperty.B_CMPT_MODE */ + this.setDolphinCmpt(PGProperty.B_CMPT_MODE.getBoolean(info)); + adaptiveSetSQLType = PGProperty.ADAPTIVE_SET_SQL_TYPE.getBoolean(info); initClientLogic(info); @@ -2101,4 +2105,22 @@ public class PgConnection implements BaseConnection { return this.adaptiveSetSQLType; } + public boolean isDolphinCmpt() { + return isDolphinCmpt; + } + + private void updateDolphinCmpt(boolean isDolphinCmpt) throws SQLException { + /* set parameter cannot use prepareStatement to set the value */ + try (Statement stmt = createStatement()) { + String sql = "set dolphin.b_compatibility_mode to " + (isDolphinCmpt ? "on" : "off"); + stmt.execute(sql); + } catch (SQLException e) { + throw e; + } + } + public void setDolphinCmpt(boolean isDolphinCmpt) throws SQLException { + checkClosed(); + updateDolphinCmpt(isDolphinCmpt); + this.isDolphinCmpt = isDolphinCmpt; + } } diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java index ee26270..60e9385 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java @@ -523,6 +523,20 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS return bytes; } + private String getBlobRaw(int i) throws SQLException { + Encoding encoding = connection.getEncoding(); + try { + return trimString(i, encoding.decode(this_row[i - 1])); + } catch (IOException ioe) { + throw new PSQLException( + GT.tr("Invalid character data was found. " + + "This is most likely caused by stored data containing characters that are invalid for the " + + "character set the database was created in. The most common example of this is storing 8bit " + + "data in a SQL_ASCII database."), + PSQLState.DATA_ERROR, ioe); + } + } + public Blob getBlob(int i) throws SQLException { checkResultSet(i); if (wasNullFlag) { @@ -538,7 +552,7 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS if (oid == Oid.BYTEA) { byt = trimBytes(i, PGbytea.toBytes(this_row[i - 1])); } else if (oid == Oid.BLOB || blobSet.contains(getPGType(i))) { - byt = toBytes(getString(i)); + byt = toBytes(getBlobRaw(i)); } else { byt = trimBytes(i, this_row[i - 1]); } @@ -2080,7 +2094,16 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS Encoding encoding = connection.getEncoding(); try { - return trimString(columnIndex, encoding.decode(this_row[columnIndex - 1])); + String typeName = getPGType(columnIndex); + String result = trimString(columnIndex, encoding.decode(this_row[columnIndex - 1])); + if (("blob".equals(typeName))) { + if (connection.unwrap(PgConnection.class).isDolphinCmpt()) { + return new String(toBytes(result)); + } + } else if (blobSet.contains(typeName)) { + return new String(toBytes(result)); + } + return result; } catch (IOException ioe) { throw new PSQLException( GT.tr( diff --git a/pgjdbc/src/test/java/org/postgresql/test/dolphintest/BlobTest.java b/pgjdbc/src/test/java/org/postgresql/test/dolphintest/BlobTest.java index e66685a..8b859b1 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/dolphintest/BlobTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/dolphintest/BlobTest.java @@ -6,6 +6,7 @@ package org.postgresql.test.dolphintest; import org.junit.Test; import org.postgresql.core.types.PGBlob; +import org.postgresql.jdbc.PgConnection; import org.postgresql.test.TestUtil; import org.postgresql.test.jdbc2.BaseTest4; @@ -28,10 +29,10 @@ public class BlobTest extends BaseTest4 { @Test public void test1() throws Exception { - String createDB = "create database test_db dbcompatibility = 'B'"; String sqlCreate = "create table if not exists t1" + "(id int, data1 tinyblob, data2 blob, data3 mediumblob, data4 longblob);"; String sqlDrop = "drop table if exists t1;"; + String sqlDropUser = "drop user test_user cascade;"; String sqlQuery = "select * from t1"; String sqlInsert = "insert into t1 values (?, ?, ?, ?, ?);"; String sqlCreateUser = "CREATE USER test_user with password 'openGauss@123'"; @@ -42,9 +43,9 @@ public class BlobTest extends BaseTest4 { /* test about not b_comp */ try (Connection con1 = TestUtil.openDB(props)) { - executeSql(con1, createDB); /* cannot create the table */ executeSql(con1, sqlCreate); + executeSql(con1, sqlDropUser); executeSql(con1, sqlCreateUser); executeSql(con1, sqlGrantUser); } @@ -62,7 +63,7 @@ public class BlobTest extends BaseTest4 { props1.put("binaryTransfer", "true"); props1.put("database", "test_db"); try (Connection con1 = TestUtil.openDB(props1)) { - executeSql(con1, "set dolphin.b_compatibility_mode=on;"); + con1.unwrap(PgConnection.class).setDolphinCmpt(true); executeSql(con1, sqlDrop); executeSql(con1, sqlCreate); try (PreparedStatement ps = con1.prepareStatement(sqlInsert)) { @@ -85,4 +86,40 @@ public class BlobTest extends BaseTest4 { } } } + @Test + public void test2() throws Exception { + Properties props1 = new Properties(); + props1.put("blobMode", "ON"); + props1.put("binaryTransfer", "true"); + props1.put("database", "test_db"); + String sqlQuery = "select * from t1"; + ResultSet set1 = null; + ResultSet set2 = null; + try (Connection con1 = TestUtil.openDB(props1)) { + con1.unwrap(PgConnection.class).setDolphinCmpt(true); + Statement statement = con1.createStatement(); + set1 = statement.executeQuery(sqlQuery); + while (set1.next()) { + assertEquals("abcdefgh\0ijklmn", set1.getString(2)); + assertEquals("abcdefgh\0ijklmn", set1.getString(3)); + assertEquals("abcdefgh\0ijklmn", set1.getString(4)); + assertEquals("abcdefgh\0ijklmn", set1.getString(5)); + } + con1.unwrap(PgConnection.class).setDolphinCmpt(false); + set2 = statement.executeQuery(sqlQuery); + while (set2.next()) { + assertEquals("abcdefgh\0ijklmn", set2.getString(2)); + assertEquals("616263646566676800696A6B6C6D6E", set2.getString(3)); + assertEquals("abcdefgh\0ijklmn", set2.getString(4)); + assertEquals("abcdefgh\0ijklmn", set2.getString(5)); + } + } finally { + if (set1 != null) { + set1.close(); + } + if (set2 != null) { + set2.close(); + } + } + } }