From 7bda6e423e7a5b1836e120c6a959537c94834a2c Mon Sep 17 00:00:00 2001 From: zhangting Date: Fri, 2 Aug 2024 14:12:13 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83getBytes=E6=96=B9=E6=B3=95=E8=8E=B7?= =?UTF-8?q?=E5=8F=96bit=E7=B1=BB=E5=9E=8B=E5=80=BC=E4=B8=8Emysql=E4=B8=80?= =?UTF-8?q?=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/postgresql/PGProperty.java | 2 + .../postgresql/core/v3/QueryExecutorImpl.java | 10 +- .../org/postgresql/jdbc/PgConnection.java | 2 +- .../java/org/postgresql/jdbc/PgDatabase.java | 103 ++++-- .../postgresql/jdbc/PgDatabaseMetaData.java | 1 + .../java/org/postgresql/jdbc/PgResultSet.java | 309 ++++++++++-------- .../org/postgresql/jdbc/TypeInfoCache.java | 86 +++-- .../org/postgresql/util/BitOutputEnum.java | 26 ++ .../java/org/postgresql/test/TestUtil.java | 14 +- .../postgresql/test/dolphintest/BitTest.java | 45 +++ .../postgresql/test/dolphintest/IntTest.java | 32 +- .../test/dolphintest/UnsignedTest.java | 260 ++++++++------- .../test/jdbc2/DatabaseMetaDataTest.java | 34 ++ .../postgresql/test/jdbc2/PGPropertyTest.java | 1 + .../org/postgresql/test/jdbc4/BitTest.java | 26 ++ 15 files changed, 603 insertions(+), 348 deletions(-) create mode 100644 pgjdbc/src/main/java/org/postgresql/util/BitOutputEnum.java diff --git a/pgjdbc/src/main/java/org/postgresql/PGProperty.java b/pgjdbc/src/main/java/org/postgresql/PGProperty.java index f2254b3..47987ce 100644 --- a/pgjdbc/src/main/java/org/postgresql/PGProperty.java +++ b/pgjdbc/src/main/java/org/postgresql/PGProperty.java @@ -612,6 +612,8 @@ public enum PGProperty { B_CMPT_MODE("BCmptMode", "true", "Specify 'dolphin.b_compatibility_mode'" + " connection initialization parameter."), + + BIT_OUTPUT("bitOutput", null, "Specify 'dolphin.bit_output' connection initialization parameter."), ; private String _name; diff --git a/pgjdbc/src/main/java/org/postgresql/core/v3/QueryExecutorImpl.java b/pgjdbc/src/main/java/org/postgresql/core/v3/QueryExecutorImpl.java index cf49165..6d109c9 100644 --- a/pgjdbc/src/main/java/org/postgresql/core/v3/QueryExecutorImpl.java +++ b/pgjdbc/src/main/java/org/postgresql/core/v3/QueryExecutorImpl.java @@ -167,7 +167,7 @@ public class QueryExecutorImpl extends QueryExecutorBase { private static final String OFF = "off"; - private static final String SERVER_SUPPORT_TRACE = "server_support_trace"; + private static final String GUC_SERVER_SUPPORT_TRACE = "enable_record_nettime"; private static final int PROTOCOL3_MSGLEN_OFFSET = 4; @@ -3215,11 +3215,9 @@ public class QueryExecutorImpl extends QueryExecutorBase { String name = pgStream.receiveString(); String value = pgStream.receiveString(); - if (name.equals(SERVER_SUPPORT_TRACE)) { - // SERVER_SUPPORT_TRACE equals "1" means server support trace - if ("1".equals(value)) { - sendSupportTrace(); - } + if (name.equals(GUC_SERVER_SUPPORT_TRACE)) { + // receive GUC_SERVER_SUPPORT_TRACE from server means server support trace + sendSupportTrace(); } if (name.equals(CLIENT_ENCODING)) { diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java index f7a37d3..81340d3 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java @@ -329,7 +329,7 @@ public class PgConnection implements BaseConnection { initObjectTypes(info); pgDatabase = new PgDatabase(this); - pgDatabase.setDolphin(); + pgDatabase.setDolphin(info); // Initialize timestamp stuff timestampUtils = new TimestampUtils(!queryExecutor.getIntegerDateTimes(), new Provider() { diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabase.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabase.java index e1078e2..c29bc56 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabase.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabase.java @@ -1,53 +1,96 @@ package org.postgresql.jdbc; -import org.postgresql.core.BaseConnection; +import org.postgresql.PGProperty; import org.postgresql.core.BaseStatement; import org.postgresql.core.QueryExecutor; import org.postgresql.util.CompatibilityEnum; import org.postgresql.util.GT; import org.postgresql.util.PSQLException; import org.postgresql.util.PSQLState; +import org.postgresql.util.BitOutputEnum; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; +import java.util.Locale; +import java.util.Properties; public class PgDatabase { - private BaseConnection connection; + private PgConnection connection; - private boolean isDolphin; + private boolean isDolphin; - public PgDatabase(BaseConnection connection) { - this.connection = connection; - } + private boolean isDec; - public boolean isDolphin() { - return isDolphin; - } + public PgDatabase(PgConnection connection) { + this.connection = connection; + } - public void setDolphin() throws SQLException { - String extensionDolphin = getDolphin("select count(1) from pg_extension where extname = 'dolphin';"); - int dolphinNum = Integer.parseInt(extensionDolphin); - String compatibility = getDolphin("show dolphin.b_compatibility_mode;"); + public boolean isDolphin() { + return isDolphin; + } - if (dolphinNum > 0 && CompatibilityEnum.ON.equals(CompatibilityEnum.valueOf(compatibility.toUpperCase()))) { - isDolphin = true; - } else { - isDolphin = false; + public boolean isDec() { + return isDec; } - } - - public String getDolphin(String sql) throws SQLException { - try (PreparedStatement dbStatement = connection.prepareStatement(sql)) { - if (!((BaseStatement) dbStatement).executeWithFlags(QueryExecutor.QUERY_SUPPRESS_BEGIN)) { - throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA); - } - try (ResultSet rs = dbStatement.getResultSet()) { - if (rs.next()) { - return rs.getString(1); + + /** + * cache dolphin + * + * @param info connection param + * @throws SQLException execute sql exception + */ + public void setDolphin(Properties info) throws SQLException { + String extensionDolphin = getDolphin("select count(1) from pg_extension where extname = 'dolphin';"); + int dolphinNum = Integer.parseInt(extensionDolphin); + String compatibility = getDolphin("show dolphin.b_compatibility_mode;"); + CompatibilityEnum compatibilityEnum = CompatibilityEnum.valueOf(compatibility.toUpperCase(Locale.ROOT)); + + if (dolphinNum > 0 && CompatibilityEnum.ON.equals(compatibilityEnum)) { + isDolphin = true; + String bitOutput = PGProperty.BIT_OUTPUT.get(info); + if (bitOutput == null) { + bitOutput = getDolphin("show dolphin.bit_output;"); + } else { + updateBitOutput(bitOutput); + } + if (BitOutputEnum.DEC.equals(BitOutputEnum.valueOf(bitOutput.toUpperCase(Locale.ROOT)))) { + isDec = true; + } + } else { + isDolphin = false; + } + } + + /** + * get dolphin + * + * @param sql execute sql + * @return dolphin of b database + * @throws SQLException execute sql exception + */ + public String getDolphin(String sql) throws SQLException { + try (PreparedStatement dbStatement = connection.prepareStatement(sql)) { + if (!((BaseStatement) dbStatement).executeWithFlags(QueryExecutor.QUERY_SUPPRESS_BEGIN)) { + throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA); + } + try (ResultSet rs = dbStatement.getResultSet()) { + if (rs.next()) { + return rs.getString(1); + } + return ""; + } + } + } + + private void updateBitOutput(String bitOutput) throws SQLException { + /* set parameter cannot use prepareStatement to set the value */ + try (Statement stmt = connection.createStatement()) { + String sql = "set dolphin.bit_output to " + bitOutput; + stmt.execute(sql); + } catch (SQLException e) { + throw e; } - return ""; - } } - } } diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java index 32aa714..2c25d0a 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java @@ -2421,6 +2421,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData { sql += ") i"; } + sql += " where (i.keys).x >= 0"; sql += " ORDER BY NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION "; return connection.createStatement().executeQuery(sql); diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java index c3e2cbf..492e432 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java @@ -256,118 +256,122 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS return getURL(findColumn(columnName)); } - protected Object internalGetObject(int columnIndex, Field field) throws SQLException { - switch (getSQLType(columnIndex)) { - case Types.BOOLEAN: - return getBoolean(columnIndex); - case Types.BIT: - return getBit(columnIndex); - case Types.SQLXML: - return getSQLXML(columnIndex); - case Types.TINYINT: - case Types.SMALLINT: - case Types.INTEGER: - return getInt(columnIndex); - case Types.BIGINT: - return getLong(columnIndex); - case TypeInfoCache.bIntegerType: - return getBigInteger(columnIndex); - case Types.NUMERIC: - case Types.DECIMAL: - int scale; - if (field.getMod() == -1) { - return getBigDecimal(columnIndex, -1); - } else { - scale = (short)((field.getMod() - 4) & 0xffff); - return getBigDecimal(columnIndex, (Math.max(scale, -1))); - } - case Types.REAL: - return getFloat(columnIndex); - case Types.FLOAT: - case Types.DOUBLE: - return getDouble(columnIndex); - case Types.CHAR: - case Types.VARCHAR: - case Types.LONGVARCHAR: - return getString(columnIndex); - case Types.DATE: - return getDate(columnIndex); - case Types.TIME: - return getTime(columnIndex); - case Types.TIMESTAMP: - return getTimestamp(columnIndex, null); - case Types.BINARY: - case Types.VARBINARY: - case Types.LONGVARBINARY: - return getBytes(columnIndex); - case Types.ARRAY: - return getArray(columnIndex); - case Types.CLOB: - return getClob(columnIndex); - case Types.BLOB: - return getBlob(columnIndex); - case Types.STRUCT: - return getStruct(columnIndex); - - default: - String type = getPGType(columnIndex); - - // if the backend doesn't know the type then coerce to String - if (type.equals("unknown")) { - return getString(columnIndex); + protected Object internalGetObject(int columnIndex, Field field) throws SQLException { + switch (getSQLType(columnIndex)) { + case Types.BOOLEAN: + return getBoolean(columnIndex); + case Types.BIT: + return getBit(columnIndex); + case Types.SQLXML: + return getSQLXML(columnIndex); + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + if (field.getPGType().equals("uint4")) { + return getLong(columnIndex); + } + return getInt(columnIndex); + case Types.BIGINT: + if (field.getPGType().equals("uint8")) { + return getBigInteger(columnIndex); + } + return getLong(columnIndex); + case Types.NUMERIC: + case Types.DECIMAL: + int scale; + if (field.getMod() == -1) { + return getBigDecimal(columnIndex, -1); + } else { + scale = (short) ((field.getMod() - 4) & 0xffff); + return getBigDecimal(columnIndex, (Math.max(scale, -1))); + } + case Types.REAL: + return getFloat(columnIndex); + case Types.FLOAT: + case Types.DOUBLE: + return getDouble(columnIndex); + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + return getString(columnIndex); + case Types.DATE: + return getDate(columnIndex); + case Types.TIME: + return getTime(columnIndex); + case Types.TIMESTAMP: + return getTimestamp(columnIndex, null); + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + return getBytes(columnIndex); + case Types.ARRAY: + return getArray(columnIndex); + case Types.CLOB: + return getClob(columnIndex); + case Types.BLOB: + return getBlob(columnIndex); + case Types.STRUCT: + return getStruct(columnIndex); + + default: + String type = getPGType(columnIndex); + + // if the backend doesn't know the type then coerce to String + if (type.equals("unknown")) { + return getString(columnIndex); + } + + if (type.equals("uuid")) { + if (isBinary(columnIndex)) { + return getUUID(this_row[columnIndex - 1]); + } + return getUUID(getString(columnIndex)); + } + + // Specialized support for ref cursors is neater. + if (type.equals("refcursor")) { + // Fetch all results. + String cursorName = getString(columnIndex); + + StringBuilder sb = new StringBuilder("FETCH ALL IN "); + Utils.escapeIdentifier(sb, cursorName); + + // nb: no BEGIN triggered here. This is fine. If someone + // committed, and the cursor was not holdable (closing the + // cursor), we avoid starting a new xact and promptly causing + // it to fail. If the cursor *was* holdable, we don't want a + // new xact anyway since holdable cursor state isn't affected + // by xact boundaries. If our caller didn't commit at all, or + // autocommit was on, then we wouldn't issue a BEGIN anyway. + // + // We take the scrollability from the statement, but until + // we have updatable cursors it must be readonly. + ResultSet rs = + connection.execSQLQuery(sb.toString(), resultsettype, ResultSet.CONCUR_READ_ONLY); + // + // In long running transactions these backend cursors take up memory space + // we could close in rs.close(), but if the transaction is closed before the result set, + // then + // the cursor no longer exists + + sb.setLength(0); + sb.append("CLOSE "); + Utils.escapeIdentifier(sb, cursorName); + connection.execSQLUpdate(sb.toString()); + ((PgResultSet) rs).setRefCursor(cursorName); + return rs; + } + if ("hstore".equals(type)) { + if (isBinary(columnIndex)) { + return HStoreConverter.fromBytes(this_row[columnIndex - 1], connection.getEncoding()); + } + return HStoreConverter.fromString(getString(columnIndex)); + } + + // Caller determines what to do (JDBC3 overrides in this case) + return null; } - - if (type.equals("uuid")) { - if (isBinary(columnIndex)) { - return getUUID(this_row[columnIndex - 1]); - } - return getUUID(getString(columnIndex)); - } - - // Specialized support for ref cursors is neater. - if (type.equals("refcursor")) { - // Fetch all results. - String cursorName = getString(columnIndex); - - StringBuilder sb = new StringBuilder("FETCH ALL IN "); - Utils.escapeIdentifier(sb, cursorName); - - // nb: no BEGIN triggered here. This is fine. If someone - // committed, and the cursor was not holdable (closing the - // cursor), we avoid starting a new xact and promptly causing - // it to fail. If the cursor *was* holdable, we don't want a - // new xact anyway since holdable cursor state isn't affected - // by xact boundaries. If our caller didn't commit at all, or - // autocommit was on, then we wouldn't issue a BEGIN anyway. - // - // We take the scrollability from the statement, but until - // we have updatable cursors it must be readonly. - ResultSet rs = - connection.execSQLQuery(sb.toString(), resultsettype, ResultSet.CONCUR_READ_ONLY); - // - // In long running transactions these backend cursors take up memory space - // we could close in rs.close(), but if the transaction is closed before the result set, - // then - // the cursor no longer exists - - sb.setLength(0); - sb.append("CLOSE "); - Utils.escapeIdentifier(sb, cursorName); - connection.execSQLUpdate(sb.toString()); - ((PgResultSet) rs).setRefCursor(cursorName); - return rs; - } - if ("hstore".equals(type)) { - if (isBinary(columnIndex)) { - return HStoreConverter.fromBytes(this_row[columnIndex - 1], connection.getEncoding()); - } - return HStoreConverter.fromString(getString(columnIndex)); - } - - // Caller determines what to do (JDBC3 overrides in this case) - return null; } - } /** * Get the PGStruct object based on parameter index @@ -2628,35 +2632,68 @@ public class PgResultSet implements ResultSet, org.postgresql.PGRefCursorResultS return toBigDecimal(getFixedString(columnIndex), scale); } - /** - * {@inheritDoc} - * - *

In normal use, the bytes represent the raw values returned by the backend. However, if the - * column is an OID, then it is assumed to refer to a Large Object, and that object is returned as - * a byte array.

- * - *

Be warned If the large object is huge, then you may run out of memory.

- */ - public byte[] getBytes(int columnIndex) throws SQLException { - connection.getLogger().trace("[" + connection.getSecSocketAddress() + "]" + " getBytes columnIndex: " + columnIndex); - checkResultSet(columnIndex); - if (wasNullFlag) { - return null; - } + /** + * {@inheritDoc} + * + *

In normal use, the bytes represent the raw values returned by the backend. However, if the + * column is an OID, then it is assumed to refer to a Large Object, and that object is returned as + * a byte array.

+ * + *

Be warned If the large object is huge, then you may run out of memory.

+ */ + public byte[] getBytes(int columnIndex) throws SQLException { + connection.getLogger().trace("[" + connection.getSecSocketAddress() + "]" + + " getBytes columnIndex: " + columnIndex); + checkResultSet(columnIndex); + if (wasNullFlag) { + return null; + } - if (isBinary(columnIndex)) { - // If the data is already binary then just return it - return this_row[columnIndex - 1]; + if (isBinary(columnIndex)) { + // If the data is already binary then just return it + return this_row[columnIndex - 1]; + } + int oid = fields[columnIndex - 1].getOID(); + if (oid == Oid.BYTEA) { + return trimBytes(columnIndex, PGbytea.toBytes(this_row[columnIndex - 1])); + } else if (oid == Oid.BLOB) { + return toBytes(getString(columnIndex)); + } else if (oid == Oid.BIT && connection.getPgDatabase().isDec()) { + return toDecBytes(fields[columnIndex - 1].getMod(), getString(columnIndex)); + } else { + return trimBytes(columnIndex, this_row[columnIndex - 1]); + } } - int oid = fields[columnIndex - 1].getOID(); - if (oid == Oid.BYTEA) { - return trimBytes(columnIndex, PGbytea.toBytes(this_row[columnIndex - 1])); - } else if (oid == Oid.BLOB) { - return toBytes(getString(columnIndex)); - } else { - return trimBytes(columnIndex, this_row[columnIndex - 1]); + + private byte[] toDecBytes(int mod, String str) { + if (mod <= 0) { + return new byte[0]; + } + int lengthToSplit = 8; + long value = Long.parseLong(str); + String binary = Long.toBinaryString(value); + int formatMod = mod; + if (mod % lengthToSplit != 0) { + formatMod = (mod / lengthToSplit + 1) * lengthToSplit; + } + + if (binary.length() < formatMod) { + StringBuilder formatBinary = new StringBuilder(); + for (int i = 0; i < formatMod - binary.length(); i++) { + formatBinary.append("0"); + } + binary = formatBinary.append(binary).toString(); + } + + int byteLength = formatMod / lengthToSplit; + byte[] bytes = new byte[byteLength]; + for (int i = 0; i < byteLength; i++) { + String splitStr = binary.substring(i * lengthToSplit, (i + 1) * lengthToSplit); + bytes[i] = (byte) Integer.parseInt(splitStr, 2); + } + + return bytes; } - } public java.sql.Date getDate(int columnIndex) throws SQLException { connection.getLogger().trace("[" + connection.getSecSocketAddress() + "]" + " getDate columnIndex: " + columnIndex); diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java b/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java index 4ecf6c0..629cd60 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java @@ -68,8 +68,6 @@ public class TypeInfoCache implements TypeInfo { private static ConcurrentHashMap pgTypes = new ConcurrentHashMap<>(); - public static final int bIntegerType = 1324; - // SELECT LENGTH(pow(10::numeric,131071)); 131071 = 2^17-1 public static final int NUMERIC_MAX_DISPLAYSIZE = 131089; @@ -77,48 +75,48 @@ public class TypeInfoCache implements TypeInfo { // openGauss accepts float(p) as numeric Type and the scale is -32768(PG_INT16_MIN) public static final int FLOATSCALE = -32768; - // basic pg types info: - // 0 - type name - // 1 - type oid - // 2 - sql type - // 3 - java class - // 4 - array type oid - private static final Object[][] types = { - {"int1", Oid.INT1, Types.TINYINT, "java.lang.Integer", Oid.INT1_ARRAY}, - {"int2", Oid.INT2, Types.SMALLINT, "java.lang.Integer", Oid.INT2_ARRAY}, - {"int4", Oid.INT4, Types.INTEGER, "java.lang.Integer", Oid.INT4_ARRAY}, - {"oid", Oid.OID, Types.BIGINT, "java.lang.Long", Oid.OID_ARRAY}, - {"int8", Oid.INT8, Types.BIGINT, "java.lang.Long", Oid.INT8_ARRAY}, - {"uint1", Oid.UINT1, Types.SMALLINT, "java.lang.Integer", Oid.UINT1_ARRAY}, - {"uint2", Oid.UINT2, Types.INTEGER, "java.lang.Integer", Oid.UINT2_ARRAY}, - {"uint4", Oid.UINT4, Types.BIGINT, "java.lang.Long", Oid.UINT4_ARRAY}, - {"uint8", Oid.UINT8, bIntegerType, "java.math.BigInteger", Oid.UINT8_ARRAY}, - {"money", Oid.MONEY, Types.DOUBLE, "java.lang.Double", Oid.MONEY_ARRAY}, - {"numeric", Oid.NUMERIC, Types.NUMERIC, "java.math.BigDecimal", Oid.NUMERIC_ARRAY}, - {"float4", Oid.FLOAT4, Types.REAL, "java.lang.Float", Oid.FLOAT4_ARRAY}, - {"float8", Oid.FLOAT8, Types.DOUBLE, "java.lang.Double", Oid.FLOAT8_ARRAY}, - {"char", Oid.CHAR, Types.CHAR, "java.lang.String", Oid.CHAR_ARRAY}, - {"bpchar", Oid.BPCHAR, Types.CHAR, "java.lang.String", Oid.BPCHAR_ARRAY}, - {"varchar", Oid.VARCHAR, Types.VARCHAR, "java.lang.String", Oid.VARCHAR_ARRAY}, - {"text", Oid.TEXT, Types.VARCHAR, "java.lang.String", Oid.TEXT_ARRAY}, - {"name", Oid.NAME, Types.VARCHAR, "java.lang.String", Oid.NAME_ARRAY}, - {"bytea", Oid.BYTEA, Types.BINARY, "[B", Oid.BYTEA_ARRAY}, - {"bool", Oid.BOOL, Types.BOOLEAN, "java.lang.Boolean", Oid.BOOL_ARRAY}, - {"bit", Oid.BIT, Types.BIT, "java.lang.Boolean", Oid.BIT_ARRAY}, - {"date", Oid.DATE, Types.DATE, "java.sql.Date", Oid.DATE_ARRAY}, - {"time", Oid.TIME, Types.TIME, "java.sql.Time", Oid.TIME_ARRAY}, - {"timetz", Oid.TIMETZ, Types.TIME, "java.sql.Time", Oid.TIMETZ_ARRAY}, - {"timestamp", Oid.TIMESTAMP, Types.TIMESTAMP, "java.sql.Timestamp", Oid.TIMESTAMP_ARRAY}, - {"smalldatetime", Oid.SMALLDATETIME, Types.TIMESTAMP, "java.lang.Timestamp", Oid.SMALLDATETIME_ARRAY}, - {"timestamptz", Oid.TIMESTAMPTZ, Types.TIMESTAMP, "java.sql.Timestamp", - Oid.TIMESTAMPTZ_ARRAY}, - {"json", Oid.JSON, Types.OTHER, "org.postgresql.util.PGobject", Oid.JSON_ARRAY}, - {"point", Oid.POINT, Types.OTHER, "org.postgresql.geometric.PGpoint", Oid.POINT_ARRAY}, - {"blob", Oid.BLOB, Types.BLOB, "org.postgresql.util.PGobject", -1}, - {"clob", Oid.CLOB, Types.CLOB, "org.postgresql.util.PGobject", -1}, - {"nvarchar2", Oid.NVARCHAR2, Types.VARCHAR, "java.lang.String", Oid.NVARCHAR2_ARRAY}, - {"refcursor", Oid.REF_CURSOR, Types.REF_CURSOR, "java.sql.ResultSet", Oid.REF_CURSOR_ARRAY} - }; + // basic pg types info: + // 0 - type name + // 1 - type oid + // 2 - sql type + // 3 - java class + // 4 - array type oid + private static final Object[][] types = { + {"int1", Oid.INT1, Types.TINYINT, "java.lang.Integer", Oid.INT1_ARRAY}, + {"int2", Oid.INT2, Types.SMALLINT, "java.lang.Integer", Oid.INT2_ARRAY}, + {"int4", Oid.INT4, Types.INTEGER, "java.lang.Integer", Oid.INT4_ARRAY}, + {"oid", Oid.OID, Types.BIGINT, "java.lang.Long", Oid.OID_ARRAY}, + {"int8", Oid.INT8, Types.BIGINT, "java.lang.Long", Oid.INT8_ARRAY}, + {"uint1", Oid.UINT1, Types.TINYINT, "java.lang.Integer", Oid.UINT1_ARRAY}, + {"uint2", Oid.UINT2, Types.SMALLINT, "java.lang.Integer", Oid.UINT2_ARRAY}, + {"uint4", Oid.UINT4, Types.INTEGER, "java.lang.Integer", Oid.UINT4_ARRAY}, + {"uint8", Oid.UINT8, Types.BIGINT, "java.lang.Long", Oid.UINT8_ARRAY}, + {"money", Oid.MONEY, Types.DOUBLE, "java.lang.Double", Oid.MONEY_ARRAY}, + {"numeric", Oid.NUMERIC, Types.NUMERIC, "java.math.BigDecimal", Oid.NUMERIC_ARRAY}, + {"float4", Oid.FLOAT4, Types.REAL, "java.lang.Float", Oid.FLOAT4_ARRAY}, + {"float8", Oid.FLOAT8, Types.DOUBLE, "java.lang.Double", Oid.FLOAT8_ARRAY}, + {"char", Oid.CHAR, Types.CHAR, "java.lang.String", Oid.CHAR_ARRAY}, + {"bpchar", Oid.BPCHAR, Types.CHAR, "java.lang.String", Oid.BPCHAR_ARRAY}, + {"varchar", Oid.VARCHAR, Types.VARCHAR, "java.lang.String", Oid.VARCHAR_ARRAY}, + {"text", Oid.TEXT, Types.VARCHAR, "java.lang.String", Oid.TEXT_ARRAY}, + {"name", Oid.NAME, Types.VARCHAR, "java.lang.String", Oid.NAME_ARRAY}, + {"bytea", Oid.BYTEA, Types.BINARY, "[B", Oid.BYTEA_ARRAY}, + {"bool", Oid.BOOL, Types.BOOLEAN, "java.lang.Boolean", Oid.BOOL_ARRAY}, + {"bit", Oid.BIT, Types.BIT, "java.lang.Boolean", Oid.BIT_ARRAY}, + {"date", Oid.DATE, Types.DATE, "java.sql.Date", Oid.DATE_ARRAY}, + {"time", Oid.TIME, Types.TIME, "java.sql.Time", Oid.TIME_ARRAY}, + {"timetz", Oid.TIMETZ, Types.TIME, "java.sql.Time", Oid.TIMETZ_ARRAY}, + {"timestamp", Oid.TIMESTAMP, Types.TIMESTAMP, "java.sql.Timestamp", Oid.TIMESTAMP_ARRAY}, + {"smalldatetime", Oid.SMALLDATETIME, Types.TIMESTAMP, "java.lang.Timestamp", Oid.SMALLDATETIME_ARRAY}, + {"timestamptz", Oid.TIMESTAMPTZ, Types.TIMESTAMP, "java.sql.Timestamp", + Oid.TIMESTAMPTZ_ARRAY}, + {"json", Oid.JSON, Types.OTHER, "org.postgresql.util.PGobject", Oid.JSON_ARRAY}, + {"point", Oid.POINT, Types.OTHER, "org.postgresql.geometric.PGpoint", Oid.POINT_ARRAY}, + {"blob", Oid.BLOB, Types.BLOB, "org.postgresql.util.PGobject", -1}, + {"clob", Oid.CLOB, Types.CLOB, "org.postgresql.util.PGobject", -1}, + {"nvarchar2", Oid.NVARCHAR2, Types.VARCHAR, "java.lang.String", Oid.NVARCHAR2_ARRAY}, + {"refcursor", Oid.REF_CURSOR, Types.REF_CURSOR, "java.sql.ResultSet", Oid.REF_CURSOR_ARRAY} + }; /** * PG maps several alias to real type names. When we do queries against pg_catalog, we must use diff --git a/pgjdbc/src/main/java/org/postgresql/util/BitOutputEnum.java b/pgjdbc/src/main/java/org/postgresql/util/BitOutputEnum.java new file mode 100644 index 0000000..180c5b1 --- /dev/null +++ b/pgjdbc/src/main/java/org/postgresql/util/BitOutputEnum.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FITFOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.postgresql.util; + +/** + * This class is used b database and bit type. + * + * @author zhangting + * @date 2024/08/10 09:01 + */ +public enum BitOutputEnum { + BIN, DEC, HEX +} diff --git a/pgjdbc/src/test/java/org/postgresql/test/TestUtil.java b/pgjdbc/src/test/java/org/postgresql/test/TestUtil.java index bc537ec..18412da 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/TestUtil.java +++ b/pgjdbc/src/test/java/org/postgresql/test/TestUtil.java @@ -42,6 +42,8 @@ public class TestUtil { public static final String SERVER_HOST_PORT_PROP = "_test_hostport"; public static final String DATABASE_PROP = "_test_database"; + private static String applicationName = "Driver Tests"; + /* * Returns the Test database JDBC URL */ @@ -50,10 +52,10 @@ public class TestUtil { } public static String getURL(String server, int port) { - return getURL(server + ":" + port, getDatabase()); + return getURL(server + ":" + port, getDatabase(), applicationName); } - public static String getURL(String hostport, String database) { + public static String getURL(String hostport, String database, String applicationName) { String logLevel = ""; if (getLogLevel() != null && !getLogLevel().equals("")) { logLevel = "&loggerLevel=" + getLogLevel(); @@ -99,10 +101,11 @@ public class TestUtil { allowEncodingChanges = "&allowEncodingChanges=" + getAllowEncodingChanges(); } + String application = "?ApplicationName=" + applicationName; return "jdbc:postgresql://" + hostport + "/" + database - + "?ApplicationName=Driver Tests" + + application + logLevel + logFile + protocolVersion @@ -412,7 +415,10 @@ public class TestUtil { String hostport = props.getProperty(SERVER_HOST_PORT_PROP, getServer() + ":" + getPort()); String database = props.getProperty(DATABASE_PROP, dbName); - return DriverManager.getConnection(getURL(hostport, database), props); + if (props.containsKey("ApplicationName")) { + return DriverManager.getConnection(getURL(hostport, database, props.get("ApplicationName").toString()), props); + } + return DriverManager.getConnection(getURL(hostport, database, applicationName), props); } /* diff --git a/pgjdbc/src/test/java/org/postgresql/test/dolphintest/BitTest.java b/pgjdbc/src/test/java/org/postgresql/test/dolphintest/BitTest.java index 2bb8f59..691ffea 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/dolphintest/BitTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/dolphintest/BitTest.java @@ -7,12 +7,20 @@ import org.postgresql.test.jdbc2.BaseTest4B; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; +import java.util.Properties; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertEquals; public class BitTest extends BaseTest4B { + @Override + protected void openDB(Properties props) throws Exception { + props.put("bitOutput", "dec"); + props.put("ApplicationName", "PostgreSQL JDBC Driver"); + super.openDB(props); + } + /* * Tests bit type */ @@ -40,4 +48,41 @@ public class BitTest extends BaseTest4B { assertEquals("class [B", o3); TestUtil.dropTable(con, "test_bit"); } + + /* + * Tests bit by getBytes() + */ + @Test + public void testBitToBytes() throws Exception { + TestUtil.createTable(con, "test_bitToBytes", "c1 bit(10),c2 bit(18)"); + String sql = "INSERT INTO test_bitToBytes VALUES (123.45, 18437.567)"; + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.executeUpdate(); + } + + try (Statement ps = con.createStatement(); + ResultSet rs = ps.executeQuery("SELECT c1,c2 FROM test_bitToBytes")) { + assertTrue(rs.next()); + String r1 = rs.getString(1); + assertNotNull(r1); + assertEquals("123", r1); + + byte[] bytes1 = rs.getBytes(1); + assertNotNull(bytes1); + assertEquals(0, bytes1[0]); + assertEquals(123, bytes1[1]); + + String r2 = rs.getString(2); + assertNotNull(r2); + assertEquals("18438", r2); + + byte[] bytes2 = rs.getBytes(2); + assertNotNull(bytes2); + assertEquals(0, bytes2[0]); + assertEquals(72, bytes2[1]); + assertEquals(6, bytes2[2]); + } finally { + TestUtil.dropTable(con, "test_bitToBytes"); + } + } } diff --git a/pgjdbc/src/test/java/org/postgresql/test/dolphintest/IntTest.java b/pgjdbc/src/test/java/org/postgresql/test/dolphintest/IntTest.java index 83a6c2d..a10ebd3 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/dolphintest/IntTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/dolphintest/IntTest.java @@ -5,12 +5,14 @@ import org.postgresql.test.TestUtil; import org.postgresql.test.jdbc2.BaseTest4B; import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.Statement; import java.sql.Types; +import java.sql.Statement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; public class IntTest extends BaseTest4B { /* @@ -116,4 +118,28 @@ public class IntTest extends BaseTest4B { TestUtil.dropTable(con, "test_tinyint2"); } + + /* + * Tests int type + */ + @Test + public void testIntType() throws Exception { + TestUtil.createTable(con, "test_int", "c1 int1,c2 int2,c3 int4," + + "c4 int8,uc1 uint1,uc2 uint2,uc3 uint4,uc4 uint8"); + try (Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT * FROM test_int")) { + ResultSetMetaData rsmd = rs.getMetaData(); + assertEquals(8, rsmd.getColumnCount()); + assertEquals(Types.TINYINT, rsmd.getColumnType(1)); + assertEquals(Types.SMALLINT, rsmd.getColumnType(2)); + assertEquals(Types.INTEGER, rsmd.getColumnType(3)); + assertEquals(Types.BIGINT, rsmd.getColumnType(4)); + assertEquals(Types.TINYINT, rsmd.getColumnType(5)); + assertEquals(Types.SMALLINT, rsmd.getColumnType(6)); + assertEquals(Types.INTEGER, rsmd.getColumnType(7)); + assertEquals(Types.BIGINT, rsmd.getColumnType(8)); + } finally { + TestUtil.dropTable(con, "test_int"); + } + } } diff --git a/pgjdbc/src/test/java/org/postgresql/test/dolphintest/UnsignedTest.java b/pgjdbc/src/test/java/org/postgresql/test/dolphintest/UnsignedTest.java index 5e3c469..946d1ca 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/dolphintest/UnsignedTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/dolphintest/UnsignedTest.java @@ -2,15 +2,21 @@ package org.postgresql.test.dolphintest; import org.junit.Assert; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; + import org.postgresql.test.TestUtil; import org.postgresql.test.jdbc2.BaseTest4B; import java.math.BigInteger; -import java.sql.*; +import java.sql.PreparedStatement; +import java.sql.Types; +import java.sql.Statement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Array; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; public class UnsignedTest extends BaseTest4B { /** @@ -21,19 +27,20 @@ public class UnsignedTest extends BaseTest4B { public void testUint1() throws SQLException { TestUtil.createTable(con, "test_unit1", "id uint1"); - PreparedStatement pstmt = con.prepareStatement("INSERT INTO test_unit1 VALUES (?)"); - pstmt.setObject(1, 234, Types.SMALLINT); - pstmt.executeUpdate(); - - Statement stmt = con.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT id FROM test_unit1"); - - assertTrue(rs.next()); - Object r1 = rs.getObject(1); - assertNotNull(r1); - assertEquals(234, r1); + try (PreparedStatement pstmt = con.prepareStatement("INSERT INTO test_unit1 VALUES (?)")) { + pstmt.setObject(1, 234, Types.SMALLINT); + pstmt.executeUpdate(); + } - TestUtil.dropTable(con, "test_unit1"); + try (Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT id FROM test_unit1");) { + assertTrue(rs.next()); + Object r1 = rs.getObject(1); + assertNotNull(r1); + assertEquals(234, r1); + } finally { + TestUtil.dropTable(con, "test_unit1"); + } } /** @@ -44,19 +51,20 @@ public class UnsignedTest extends BaseTest4B { public void testUint2() throws SQLException { TestUtil.createTable(con, "test_unit2", "id uint2"); - PreparedStatement pstmt = con.prepareStatement("INSERT INTO test_unit2 VALUES (?)"); - pstmt.setObject(1, 65518, Types.INTEGER); - pstmt.executeUpdate(); - - Statement stmt = con.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT id FROM test_unit2"); - - assertTrue(rs.next()); - Object r1 = rs.getObject(1); - assertNotNull(r1); - assertEquals(65518, r1); + try (PreparedStatement pstmt = con.prepareStatement("INSERT INTO test_unit2 VALUES (?)")) { + pstmt.setObject(1, 65518, Types.INTEGER); + pstmt.executeUpdate(); + } - TestUtil.dropTable(con, "test_unit2"); + try (Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT id FROM test_unit2")) { + assertTrue(rs.next()); + Object r1 = rs.getObject(1); + assertNotNull(r1); + assertEquals(65518, r1); + } finally { + TestUtil.dropTable(con, "test_unit2"); + } } /** @@ -67,20 +75,20 @@ public class UnsignedTest extends BaseTest4B { public void testUint4() throws SQLException { TestUtil.createTable(con, "test_unit4", "id uint4"); - PreparedStatement pstmt = con.prepareStatement("INSERT INTO test_unit4 VALUES (?)"); - long l = 4294967282L; - pstmt.setObject(1, l, Types.BIGINT); - pstmt.executeUpdate(); - - Statement stmt = con.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT id FROM test_unit4"); - - assertTrue(rs.next()); - Object r1 = rs.getObject(1); - assertNotNull(r1); - assertEquals(l, r1); + try (PreparedStatement pstmt = con.prepareStatement("INSERT INTO test_unit4 VALUES (?)")) { + pstmt.setObject(1, 4294967282L, Types.BIGINT); + pstmt.executeUpdate(); + } - TestUtil.dropTable(con, "test_unit4"); + try (Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT id FROM test_unit4")) { + assertTrue(rs.next()); + Object r1 = rs.getObject(1); + assertNotNull(r1); + assertEquals(4294967282L, r1); + } finally { + TestUtil.dropTable(con, "test_unit4"); + } } /** @@ -90,109 +98,113 @@ public class UnsignedTest extends BaseTest4B { @Test public void testUint8() throws SQLException { TestUtil.createTable(con, "test_unit8", "id uint8"); - - PreparedStatement pstmt = con.prepareStatement("INSERT INTO test_unit8 VALUES (?)"); BigInteger b = new BigInteger("9223372036859999999"); - pstmt.setObject(1, b, Types.NUMERIC); - pstmt.executeUpdate(); - BigInteger b2 = new BigInteger("15223372036859999999"); - pstmt.setObject(1, b2, Types.NUMERIC); - pstmt.executeUpdate(); + try (PreparedStatement pstmt = con.prepareStatement("INSERT INTO test_unit8 VALUES (?)")) { + pstmt.setObject(1, b, Types.NUMERIC); + pstmt.executeUpdate(); - Statement stmt = con.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT id FROM test_unit8"); - - assertTrue(rs.next()); - Object r1 = rs.getObject(1); - assertNotNull(r1); - assertEquals(b, r1); - - assertTrue(rs.next()); - Object r2 = rs.getObject(1); - assertNotNull(r2); - assertEquals(b2, r2); + pstmt.setObject(1, b2, Types.NUMERIC); + pstmt.executeUpdate(); + } - TestUtil.dropTable(con, "test_unit8"); + try (Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT id FROM test_unit8")) { + assertTrue(rs.next()); + Object r1 = rs.getObject(1); + assertNotNull(r1); + assertEquals(b, r1); + + assertTrue(rs.next()); + Object r2 = rs.getObject(1); + assertNotNull(r2); + assertEquals(b2, r2); + } finally { + TestUtil.dropTable(con, "test_unit8"); + } } @Test public void testCreateArrayOfUint1() throws SQLException { - PreparedStatement pstmt = con.prepareStatement("SELECT ?::uint1[]"); - Short[] in = new Short[3]; - in[0] = 0; - in[1] = 188; - in[2] = 234; - pstmt.setArray(1, con.createArrayOf("uint1", in)); - - ResultSet rs = pstmt.executeQuery(); - Assert.assertTrue(rs.next()); - Array arr = rs.getArray(1); - Short[] out = (Short[]) arr.getArray(); - - Assert.assertEquals(3, out.length); - Assert.assertEquals(0, out[0].shortValue()); - Assert.assertEquals(188, out[1].shortValue()); - Assert.assertEquals(234, out[2].shortValue()); + try (PreparedStatement pstmt = con.prepareStatement("SELECT ?::uint1[]")) { + Object[] in = new Object[3]; + in[0] = 0; + in[1] = 88; + in[2] = 115; + pstmt.setArray(1, con.createArrayOf("uint1", in)); + try (ResultSet rs = pstmt.executeQuery()) { + Assert.assertTrue(rs.next()); + Array arr = rs.getArray(1); + Object[] out = (Object[]) arr.getArray(); + + Assert.assertEquals(3, out.length); + Assert.assertEquals(0, Integer.parseInt(out[0].toString())); + Assert.assertEquals(88, Integer.parseInt(out[1].toString())); + Assert.assertEquals(115, Integer.parseInt(out[2].toString())); + } + } } @Test public void testCreateArrayOfUint2() throws SQLException { - PreparedStatement pstmt = con.prepareStatement("SELECT ?::uint2[]"); - Integer[] in = new Integer[3]; - in[0] = 0; - in[1] = 12654; - in[2] = 65535; - pstmt.setArray(1, con.createArrayOf("uint2", in)); - - ResultSet rs = pstmt.executeQuery(); - Assert.assertTrue(rs.next()); - Array arr = rs.getArray(1); - Integer[] out = (Integer[]) arr.getArray(); - - Assert.assertEquals(3, out.length); - Assert.assertEquals(0, out[0].intValue()); - Assert.assertEquals(12654, out[1].intValue()); - Assert.assertEquals(65535, out[2].intValue()); + try (PreparedStatement pstmt = con.prepareStatement("SELECT ?::uint2[]")) { + Short[] in = new Short[3]; + in[0] = 0; + in[1] = 12654; + in[2] = 30035; + pstmt.setArray(1, con.createArrayOf("uint2", in)); + try (ResultSet rs = pstmt.executeQuery()) { + Assert.assertTrue(rs.next()); + Array arr = rs.getArray(1); + Short[] out = (Short[]) arr.getArray(); + + Assert.assertEquals(3, out.length); + Assert.assertEquals(0, out[0].shortValue()); + Assert.assertEquals(12654, out[1].shortValue()); + Assert.assertEquals(30035, out[2].shortValue()); + } + } } @Test public void testCreateArrayOfUint4() throws SQLException { - PreparedStatement pstmt = con.prepareStatement("SELECT ?::uint4[]"); - Long[] in = new Long[2]; - in[0] = 0L; - in[1] = 4294967295L; - pstmt.setArray(1, con.createArrayOf("uint4", in)); - - ResultSet rs = pstmt.executeQuery(); - Assert.assertTrue(rs.next()); - Array arr = rs.getArray(1); - Long[] out = (Long[]) arr.getArray(); - - Assert.assertEquals(2, out.length); - Assert.assertEquals(0, out[0].longValue()); - Assert.assertEquals(4294967295L, out[1].longValue()); + try (PreparedStatement pstmt = con.prepareStatement("SELECT ?::uint4[]")) { + Integer[] in = new Integer[2]; + in[0] = 0; + in[1] = 1994967295; + pstmt.setArray(1, con.createArrayOf("uint4", in)); + try (ResultSet rs = pstmt.executeQuery()) { + Assert.assertTrue(rs.next()); + Array arr = rs.getArray(1); + Integer[] out = (Integer[]) arr.getArray(); + + Assert.assertEquals(2, out.length); + Assert.assertEquals(0, out[0].intValue()); + Assert.assertEquals(1994967295, out[1].intValue()); + } + } } @Test public void testCreateArrayOfUint8() throws SQLException { - PreparedStatement pstmt = con.prepareStatement("SELECT ?::uint8[]"); - Long[] in = new Long[2]; - in[0] = 0L; - in[1] = 32458765334567556L; - pstmt.setArray(1, con.createArrayOf("uint8", in)); - - ResultSet rs = pstmt.executeQuery(); - Assert.assertTrue(rs.next()); - Array arr = rs.getArray(1); - Object[] out = (Object[]) arr.getArray(); - Long[] outLong = new Long[out.length]; - for (int i = 0; i < out.length; i++) { - outLong[i] = Long.valueOf(out[i].toString()); + try (PreparedStatement pstmt = con.prepareStatement("SELECT ?::uint8[]")) { + Long[] in = new Long[2]; + in[0] = 0L; + in[1] = 32458765334567556L; + pstmt.setArray(1, con.createArrayOf("uint8", in)); + try (ResultSet rs = pstmt.executeQuery()) { + Assert.assertTrue(rs.next()); + Array arr = rs.getArray(1); + Object[] out = (Object[]) arr.getArray(); + Long[] outLong = new Long[out.length]; + for (int i = 0; i < out.length; i++) { + outLong[i] = Long.valueOf(out[i].toString()); + } + + Assert.assertEquals(2, out.length); + Assert.assertEquals(0L, outLong[0].longValue()); + Assert.assertEquals(32458765334567556L, outLong[1].longValue()); + } } - - Assert.assertEquals(2, out.length); - Assert.assertEquals(0L, outLong[0].longValue()); - Assert.assertEquals(32458765334567556L, outLong[1].longValue()); } } diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java index 047fc94..f4c2834 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java @@ -1332,4 +1332,38 @@ public class DatabaseMetaDataTest { } } + @Test + public void testPrimaryKey() throws SQLException { + try (Statement stmt = con.createStatement()) { + stmt.execute("drop table if exists test_metadata"); + stmt.execute("CREATE TABLE test_metadata (\n" + + " col_pk numeric NOT NULL primary key,\n" + + " partition_col character varying(30) NOT NULL\n" + + ")\n" + + "WITH (orientation=row, compression=no)\n" + + "PARTITION BY LIST (partition_col)\n" + + "(\n" + + " PARTITION partition_col_id_0100 VALUES ('0100') ,\n" + + " PARTITION partition_col_id_0110 VALUES ('0110') ,\n" + + " PARTITION partition_col_id_other VALUES (DEFAULT)\n" + + ");"); + } + DatabaseMetaData metaData = con.getMetaData(); + try (ResultSet rs = metaData.getPrimaryKeys("", "public", "test_metadata")) { + assertTrue(rs.next()); + assertEquals("col_pk", rs.getString(4)); + assertEquals(1, rs.getInt(5)); + assertFalse(rs.next()); + } + + try (ResultSet rs1 = metaData.getIndexInfo("", "public", + "test_metadata", true, true)) { + assertTrue(rs1.next()); + assertEquals("test_metadata_pkey", rs1.getString(6)); + assertEquals("col_pk", rs1.getString(9)); + assertFalse(rs1.next()); + } + + TestUtil.dropTable(con, "test_metadata"); + } } diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PGPropertyTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PGPropertyTest.java index 257dd53..f1d0f2d 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PGPropertyTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PGPropertyTest.java @@ -153,6 +153,7 @@ public class PGPropertyTest { excluded.add("enableStatementLoadBalance"); excluded.add("writeDataSourceAddress"); excluded.add("BCmptMode"); + excluded.add("bitOutput"); // index PropertyDescriptors by name Map propertyDescriptors = diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc4/BitTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc4/BitTest.java index ec53561..d50364f 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc4/BitTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc4/BitTest.java @@ -40,4 +40,30 @@ public class BitTest extends BaseTest4 { assertEquals(true, o3); TestUtil.dropTable(con, "test_bit"); } + + /* + * Tests bit by getBytes() + */ + @Test + public void testBitToBytes() throws Exception { + TestUtil.createTable(con, "test_bitToBytes", "c1 bit(10),c2 bit(18)"); + String sql = "INSERT INTO test_bitToBytes VALUES (123::bit(10), 18437::bit(18))"; + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.executeUpdate(); + } + + try (Statement ps = con.createStatement(); + ResultSet rs = ps.executeQuery("SELECT c1,c2 FROM test_bitToBytes")) { + assertTrue(rs.next()); + String r1 = rs.getString(1); + assertNotNull(r1); + assertEquals("0001111011", r1); + + String r2 = rs.getString(2); + assertNotNull(r2); + assertEquals("000100100000000101", r2); + } finally { + TestUtil.dropTable(con, "test_bitToBytes"); + } + } } -- Gitee