From 9f02b1435fe2033289df62c9fc7229da5908c293 Mon Sep 17 00:00:00 2001 From: Dave Cramer Date: Tue, 12 Nov 2019 12:06:42 -0500 Subject: [PATCH 1/2] fix: get correct column length for simple domains --- .../postgresql/jdbc/PgDatabaseMetaData.java | 39 +++++++++++++++---- .../test/jdbc2/DatabaseMetaDataTest.java | 15 ++++++- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java index 56d135065c..26e2e9b2bf 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java @@ -1497,7 +1497,7 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa } sql += "SELECT n.nspname,c.relname,a.attname,a.atttypid,a.attnotnull " - + "OR (t.typtype = 'd' AND t.typnotnull) AS attnotnull,a.atttypmod,a.attlen,"; + + "OR (t.typtype = 'd' AND t.typnotnull) AS attnotnull,a.atttypmod,a.attlen,t.typtypmod,"; if (connection.haveMinimumServerVersion(ServerVersion.v8_4)) { sql += "row_number() OVER (PARTITION BY a.attrelid ORDER BY a.attnum) AS attnum, "; @@ -1580,12 +1580,37 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa } String identity = rs.getString("attidentity"); - int decimalDigits = connection.getTypeInfo().getScale(typeOid, typeMod); - int columnSize = connection.getTypeInfo().getPrecision(typeOid, typeMod); - if (columnSize == 0) { - columnSize = connection.getTypeInfo().getDisplaySize(typeOid, typeMod); - } + int baseTypeOid = (int) rs.getLong("typbasetype"); + int decimalDigits; + int columnSize; + + /* this is really a DOMAIN type not sure where DISTINCT came from */ + if ( sqlType == Types.DISTINCT ) { + /* + From the docs if typtypmod is -1 + */ + int domainLength = rs.getInt("typtypmod"); + decimalDigits = connection.getTypeInfo().getScale(baseTypeOid, typeMod); + /* + From the postgres docs: + Domains use typtypmod to record the typmod to be applied to their + base type (-1 if base type does not use a typmod). -1 if this type is not a domain. + if it is -1 then get the precision from the basetype. This doesn't help if the basetype is + a domain, but for actual types this will return the correct value. + */ + if ( domainLength == -1 ) { + columnSize = connection.getTypeInfo().getPrecision(baseTypeOid, typeMod); + } else { + columnSize = domainLength; + } + } else { + decimalDigits = connection.getTypeInfo().getScale(typeOid, typeMod); + columnSize = connection.getTypeInfo().getPrecision(typeOid, typeMod); + if (columnSize == 0) { + columnSize = connection.getTypeInfo().getDisplaySize(typeOid, typeMod); + } + } tuple[6] = connection.encodeString(Integer.toString(columnSize)); tuple[8] = connection.encodeString(Integer.toString(decimalDigits)); @@ -1607,8 +1632,6 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa // Is nullable tuple[17] = connection.encodeString(rs.getBoolean("attnotnull") ? "NO" : "YES"); - int baseTypeOid = (int) rs.getLong("typbasetype"); - tuple[18] = null; // SCOPE_CATLOG tuple[19] = null; // SCOPE_SCHEMA tuple[20] = null; // SCOPE_TABLE 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 0e3f6055d0..5a2c0672ed 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java @@ -83,7 +83,8 @@ public void setUp() throws Exception { } TestUtil.createDomain(con, "nndom", "int not null"); - TestUtil.createTable(con, "domaintable", "id nndom"); + TestUtil.createDomain(con, "varbit2", "varbit(3)"); + TestUtil.createTable(con, "domaintable", "id nndom, v varbit2"); stmt.close(); } @@ -673,6 +674,18 @@ public void testNotNullDomainColumn() throws SQLException { assertTrue(!rs.next()); } + @Test + public void testDomainColumnSize() throws SQLException { + DatabaseMetaData dbmd = con.getMetaData(); + ResultSet rs = dbmd.getColumns("", "", "domaintable", ""); + assertTrue(rs.next()); + assertEquals("id", rs.getString("COLUMN_NAME")); + assertEquals(10, rs.getInt("COLUMN_SIZE")); + assertTrue(rs.next()); + assertEquals("v", rs.getString("COLUMN_NAME")); + assertEquals(3, rs.getInt("COLUMN_SIZE")); + } + @Test public void testAscDescIndexInfo() throws SQLException { if (!TestUtil.haveMinimumServerVersion(con, ServerVersion.v8_3)) { From 60bc5a98463a96543ec30270f3015601c2840a55 Mon Sep 17 00:00:00 2001 From: Dave Cramer Date: Tue, 12 Nov 2019 13:13:31 -0500 Subject: [PATCH 2/2] fix failing test --- .../java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java | 1 + 1 file changed, 1 insertion(+) 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 5a2c0672ed..e8e031404f 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java @@ -671,6 +671,7 @@ public void testNotNullDomainColumn() throws SQLException { assertTrue(rs.next()); assertEquals("id", rs.getString("COLUMN_NAME")); assertEquals("NO", rs.getString("IS_NULLABLE")); + assertTrue(rs.next()); assertTrue(!rs.next()); }