Skip to content

Commit

Permalink
feat: add way to distinguish base and partitioned tables in PgDatabas…
Browse files Browse the repository at this point in the history
…eMetaData.getTables (#1708)

* feat: add way to distinguish base and partitioned tables in PgDatabaseMetaData.getTables

There is currently no way to distinguish between base tables and
partitioned tables in the response from PgDatabadeMetaData.getTables.
Fix this by adding PARTITIONED TABLE to the tableTypeClauses map and
thus the TABLE_TYPE field in the query in getTables. Also update a test
(testPartitionedTables) that was using TABLE_TYPE of TABLE to grab
partitioned tables.

This should close #1590. However, perhaps this could be considered a
breaking change for anyone using getTables and expecting partitioned
tables to show up for .getTables(s, s1, s2, new String[]{"TABLE"})?

* test: improve database metadata table type test
  • Loading branch information
MSGoodman committed Feb 25, 2020
1 parent 13a644b commit 25eb32c
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 6 deletions.
11 changes: 7 additions & 4 deletions pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java
Expand Up @@ -1284,7 +1284,7 @@ public ResultSet getTables(String catalog, String schemaPattern, String tableNam
+ " END "
+ " WHEN false THEN CASE c.relkind "
+ " WHEN 'r' THEN 'TABLE' "
+ " WHEN 'p' THEN 'TABLE' "
+ " WHEN 'p' THEN 'PARTITIONED TABLE' "
+ " WHEN 'i' THEN 'INDEX' "
+ " WHEN 'S' THEN 'SEQUENCE' "
+ " WHEN 'v' THEN 'VIEW' "
Expand Down Expand Up @@ -1339,9 +1339,12 @@ public ResultSet getTables(String catalog, String schemaPattern, String tableNam
tableTypeClauses = new HashMap<String, Map<String, String>>();
Map<String, String> ht = new HashMap<String, String>();
tableTypeClauses.put("TABLE", ht);
ht.put("SCHEMAS",
"c.relkind IN ('r','p') AND n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'");
ht.put("NOSCHEMAS", "c.relkind IN ('r','p') AND c.relname !~ '^pg_'");
ht.put("SCHEMAS", "c.relkind = 'r' AND n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'");
ht.put("NOSCHEMAS", "c.relkind = 'r' AND c.relname !~ '^pg_'");
ht = new HashMap<String, String>();
tableTypeClauses.put("PARTITIONED TABLE", ht);
ht.put("SCHEMAS", "c.relkind = 'p' AND n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'");
ht.put("NOSCHEMAS", "c.relkind = 'p' AND c.relname !~ '^pg_'");
ht = new HashMap<String, String>();
tableTypeClauses.put("VIEW", ht);
ht.put("SCHEMAS",
Expand Down
Expand Up @@ -29,6 +29,7 @@
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -758,11 +759,27 @@ public void testPartialIndexInfo() throws SQLException {

@Test
public void testTableTypes() throws SQLException {
// At the moment just test that no exceptions are thrown KJ
final List<String> expectedTableTypes = new ArrayList<String>(Arrays.asList("FOREIGN TABLE", "INDEX",
"MATERIALIZED VIEW", "PARTITIONED TABLE", "SEQUENCE", "SYSTEM INDEX", "SYSTEM TABLE", "SYSTEM TOAST INDEX",
"SYSTEM TOAST TABLE", "SYSTEM VIEW", "TABLE", "TEMPORARY INDEX", "TEMPORARY SEQUENCE", "TEMPORARY TABLE",
"TEMPORARY VIEW", "TYPE", "VIEW"));
final List<String> foundTableTypes = new ArrayList<String>();

// Test that no exceptions are thrown
DatabaseMetaData dbmd = con.getMetaData();
assertNotNull(dbmd);

// Test that the table types returned are the same as those expected
ResultSet rs = dbmd.getTableTypes();
while (rs.next()) {
String tableType = new String(rs.getBytes(1));
foundTableTypes.add(tableType);
}
rs.close();
Collections.sort(expectedTableTypes);
Collections.sort(foundTableTypes);
Assert.assertEquals("The table types received from DatabaseMetaData should match the 17 expected types",
true, foundTableTypes.equals(expectedTableTypes));
}

@Test
Expand Down Expand Up @@ -1270,7 +1287,7 @@ public void testPartitionedTables() throws SQLException {
stmt.execute(
"CREATE TABLE measurement (logdate date not null,peaktemp int,unitsales int ) PARTITION BY RANGE (logdate);");
DatabaseMetaData dbmd = con.getMetaData();
ResultSet rs = dbmd.getTables("", "", "measurement", new String[]{"TABLE"});
ResultSet rs = dbmd.getTables("", "", "measurement", new String[]{"PARTITIONED TABLE"});
assertTrue(rs.next());
assertEquals("measurement", rs.getString("table_name"));

Expand Down

7 comments on commit 25eb32c

@amarchanka
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our product using Hibernate and postgresql. Because we have partitioned tables we got error on start:
org.hibernate.HibernateException: Missing table: TRADE_ORDER
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1335)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:175)
at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:525)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)

Could you suggest how to use newest pgjdbc?

@davecramer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to have a very small example to work with here.

@amarchanka
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to have a very small example to work with here.
Step to reproduce:

  1. Create partitioned table. (I hope you know how to do it. I don't know.)
  2. Create hibernate mapping. we have problem with hibernate - 4.3.11
  3. Launch application.

@davecramer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need/want code for a very simple hibernate project. I can certainly create the table

@amarchanka
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need/want code for a very simple hibernate project. I can certainly create the table
Ok, I'll try to create it on weekend.

@davecramer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amarchanka
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.