@@ -1479,6 +1479,7 @@ describeOneTableDetails(const char *schemaname,
14791479bool rowsecurity ;
14801480bool forcerowsecurity ;
14811481bool hasoids ;
1482+ bool ispartition ;
14821483Oid tablespace ;
14831484char * reloptions ;
14841485char * reloftype ;
@@ -1502,7 +1503,7 @@ describeOneTableDetails(const char *schemaname,
15021503printfPQExpBuffer (& buf ,
15031504"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
15041505"c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
1505- "false AS relhasoids, %s, c.reltablespace, "
1506+ "false AS relhasoids,c.relispartition, %s, c.reltablespace, "
15061507"CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
15071508"c.relpersistence, c.relreplident, am.amname\n"
15081509"FROM pg_catalog.pg_class c\n "
@@ -1515,12 +1516,29 @@ describeOneTableDetails(const char *schemaname,
15151516 :"''" ),
15161517oid );
15171518}
1519+ else if (pset .sversion >=100000 )
1520+ {
1521+ printfPQExpBuffer (& buf ,
1522+ "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
1523+ "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
1524+ "c.relhasoids, c.relispartition, %s, c.reltablespace, "
1525+ "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
1526+ "c.relpersistence, c.relreplident\n"
1527+ "FROM pg_catalog.pg_class c\n "
1528+ "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
1529+ "WHERE c.oid = '%s';" ,
1530+ (verbose ?
1531+ "pg_catalog.array_to_string(c.reloptions || "
1532+ "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
1533+ :"''" ),
1534+ oid );
1535+ }
15181536else if (pset .sversion >=90500 )
15191537{
15201538printfPQExpBuffer (& buf ,
15211539"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
15221540"c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
1523- "c.relhasoids, %s, c.reltablespace, "
1541+ "c.relhasoids,false as relispartition, %s, c.reltablespace, "
15241542"CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
15251543"c.relpersistence, c.relreplident\n"
15261544"FROM pg_catalog.pg_class c\n "
@@ -1537,7 +1555,7 @@ describeOneTableDetails(const char *schemaname,
15371555printfPQExpBuffer (& buf ,
15381556"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
15391557"c.relhastriggers, false, false, c.relhasoids, "
1540- "%s, c.reltablespace, "
1558+ "false as relispartition, %s, c.reltablespace, "
15411559"CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
15421560"c.relpersistence, c.relreplident\n"
15431561"FROM pg_catalog.pg_class c\n "
@@ -1554,7 +1572,7 @@ describeOneTableDetails(const char *schemaname,
15541572printfPQExpBuffer (& buf ,
15551573"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
15561574"c.relhastriggers, false, false, c.relhasoids, "
1557- "%s, c.reltablespace, "
1575+ "false as relispartition, %s, c.reltablespace, "
15581576"CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
15591577"c.relpersistence\n"
15601578"FROM pg_catalog.pg_class c\n "
@@ -1571,7 +1589,7 @@ describeOneTableDetails(const char *schemaname,
15711589printfPQExpBuffer (& buf ,
15721590"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
15731591"c.relhastriggers, false, false, c.relhasoids, "
1574- "%s, c.reltablespace, "
1592+ "false as relispartition, %s, c.reltablespace, "
15751593"CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END\n"
15761594"FROM pg_catalog.pg_class c\n "
15771595"LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
@@ -1587,7 +1605,7 @@ describeOneTableDetails(const char *schemaname,
15871605printfPQExpBuffer (& buf ,
15881606"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
15891607"c.relhastriggers, false, false, c.relhasoids, "
1590- "%s, c.reltablespace\n"
1608+ "false as relispartition, %s, c.reltablespace\n"
15911609"FROM pg_catalog.pg_class c\n "
15921610"LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
15931611"WHERE c.oid = '%s';" ,
@@ -1602,7 +1620,7 @@ describeOneTableDetails(const char *schemaname,
16021620printfPQExpBuffer (& buf ,
16031621"SELECT relchecks, relkind, relhasindex, relhasrules, "
16041622"reltriggers <> 0, false, false, relhasoids, "
1605- "%s, reltablespace\n"
1623+ "false as relispartition, %s, reltablespace\n"
16061624"FROM pg_catalog.pg_class WHERE oid = '%s';" ,
16071625 (verbose ?
16081626"pg_catalog.array_to_string(reloptions, E', ')" :"''" ),
@@ -1613,7 +1631,7 @@ describeOneTableDetails(const char *schemaname,
16131631printfPQExpBuffer (& buf ,
16141632"SELECT relchecks, relkind, relhasindex, relhasrules, "
16151633"reltriggers <> 0, false, false, relhasoids, "
1616- "'', reltablespace\n"
1634+ "false as relispartition, '', reltablespace\n"
16171635"FROM pg_catalog.pg_class WHERE oid = '%s';" ,
16181636oid );
16191637}
@@ -1622,7 +1640,7 @@ describeOneTableDetails(const char *schemaname,
16221640printfPQExpBuffer (& buf ,
16231641"SELECT relchecks, relkind, relhasindex, relhasrules, "
16241642"reltriggers <> 0, false, false, relhasoids, "
1625- "'', ''\n"
1643+ "false as relispartition, '', ''\n"
16261644"FROM pg_catalog.pg_class WHERE oid = '%s';" ,
16271645oid );
16281646}
@@ -1647,20 +1665,21 @@ describeOneTableDetails(const char *schemaname,
16471665tableinfo .rowsecurity = strcmp (PQgetvalue (res ,0 ,5 ),"t" )== 0 ;
16481666tableinfo .forcerowsecurity = strcmp (PQgetvalue (res ,0 ,6 ),"t" )== 0 ;
16491667tableinfo .hasoids = strcmp (PQgetvalue (res ,0 ,7 ),"t" )== 0 ;
1668+ tableinfo .ispartition = strcmp (PQgetvalue (res ,0 ,8 ),"t" )== 0 ;
16501669tableinfo .reloptions = (pset .sversion >=80200 ) ?
1651- pg_strdup (PQgetvalue (res ,0 ,8 )) :NULL ;
1670+ pg_strdup (PQgetvalue (res ,0 ,9 )) :NULL ;
16521671tableinfo .tablespace = (pset .sversion >=80000 ) ?
1653- atooid (PQgetvalue (res ,0 ,9 )) :0 ;
1672+ atooid (PQgetvalue (res ,0 ,10 )) :0 ;
16541673tableinfo .reloftype = (pset .sversion >=90000 &&
1655- strcmp (PQgetvalue (res ,0 ,10 ),"" )!= 0 ) ?
1656- pg_strdup (PQgetvalue (res ,0 ,10 )) :NULL ;
1674+ strcmp (PQgetvalue (res ,0 ,11 ),"" )!= 0 ) ?
1675+ pg_strdup (PQgetvalue (res ,0 ,11 )) :NULL ;
16571676tableinfo .relpersistence = (pset .sversion >=90100 ) ?
1658- * (PQgetvalue (res ,0 ,11 )) :0 ;
1677+ * (PQgetvalue (res ,0 ,12 )) :0 ;
16591678tableinfo .relreplident = (pset .sversion >=90400 ) ?
1660- * (PQgetvalue (res ,0 ,12 )) :'d' ;
1679+ * (PQgetvalue (res ,0 ,13 )) :'d' ;
16611680if (pset .sversion >=120000 )
1662- tableinfo .relam = PQgetisnull (res ,0 ,13 ) ?
1663- (char * )NULL :pg_strdup (PQgetvalue (res ,0 ,13 ));
1681+ tableinfo .relam = PQgetisnull (res ,0 ,14 ) ?
1682+ (char * )NULL :pg_strdup (PQgetvalue (res ,0 ,14 ));
16641683else
16651684tableinfo .relam = NULL ;
16661685PQclear (res );
@@ -2394,12 +2413,36 @@ describeOneTableDetails(const char *schemaname,
23942413if (tableinfo .hastriggers ||
23952414tableinfo .relkind == RELKIND_PARTITIONED_TABLE )
23962415{
2397- printfPQExpBuffer (& buf ,
2398- "SELECT conname,\n"
2399- " pg_catalog.pg_get_constraintdef(r.oid, true) as condef\n"
2400- "FROM pg_catalog.pg_constraint r\n"
2401- "WHERE r.conrelid = '%s' AND r.contype = 'f' ORDER BY 1;" ,
2402- oid );
2416+ if (pset .sversion >=120000 &&
2417+ (tableinfo .ispartition || tableinfo .relkind == RELKIND_PARTITIONED_TABLE ))
2418+ {
2419+ /*
2420+ * Put the constraints defined in this table first, followed
2421+ * by the constraints defined in ancestor partitioned tables.
2422+ */
2423+ printfPQExpBuffer (& buf ,
2424+ "SELECT conrelid = '%s'::pg_catalog.regclass AS sametable,\n"
2425+ " conname,\n"
2426+ " pg_catalog.pg_get_constraintdef(oid, true) AS condef,\n"
2427+ " conrelid::pg_catalog.regclass AS ontable\n"
2428+ " FROM pg_catalog.pg_constraint,\n"
2429+ " pg_catalog.pg_partition_ancestors('%s')\n"
2430+ " WHERE conrelid = relid AND contype = 'f' AND conparentid = 0\n"
2431+ "ORDER BY sametable DESC, conname;" ,
2432+ oid ,oid );
2433+ }
2434+ else
2435+ {
2436+ printfPQExpBuffer (& buf ,
2437+ "SELECT true as sametable, conname,\n"
2438+ " pg_catalog.pg_get_constraintdef(r.oid, true) as condef,\n"
2439+ " conrelid::pg_catalog.regclass AS ontable\n"
2440+ "FROM pg_catalog.pg_constraint r\n"
2441+ "WHERE r.conrelid = '%s' AND r.contype = 'f'\n"
2442+ "ORDER BY conname;" ,
2443+ oid );
2444+ }
2445+
24032446result = PSQLexec (buf .data );
24042447if (!result )
24052448gotoerror_return ;
@@ -2408,29 +2451,62 @@ describeOneTableDetails(const char *schemaname,
24082451
24092452if (tuples > 0 )
24102453{
2454+ int i_sametable = PQfnumber (result ,"sametable" ),
2455+ i_conname = PQfnumber (result ,"conname" ),
2456+ i_condef = PQfnumber (result ,"condef" ),
2457+ i_ontable = PQfnumber (result ,"ontable" );
2458+
24112459printTableAddFooter (& cont ,_ ("Foreign-key constraints:" ));
24122460for (i = 0 ;i < tuples ;i ++ )
24132461{
2414- /* untranslated constraint name and def */
2415- printfPQExpBuffer (& buf ," \"%s\" %s" ,
2416- PQgetvalue (result ,i ,0 ),
2417- PQgetvalue (result ,i ,1 ));
2462+ /*
2463+ * Print untranslated constraint name and definition. Use
2464+ * a "TABLE tab" prefix when the constraint is defined in
2465+ * a parent partitioned table.
2466+ */
2467+ if (strcmp (PQgetvalue (result ,i ,i_sametable ),"f" )== 0 )
2468+ printfPQExpBuffer (& buf ," TABLE \"%s\" CONSTRAINT \"%s\" %s" ,
2469+ PQgetvalue (result ,i ,i_ontable ),
2470+ PQgetvalue (result ,i ,i_conname ),
2471+ PQgetvalue (result ,i ,i_condef ));
2472+ else
2473+ printfPQExpBuffer (& buf ," \"%s\" %s" ,
2474+ PQgetvalue (result ,i ,i_conname ),
2475+ PQgetvalue (result ,i ,i_condef ));
24182476
24192477printTableAddFooter (& cont ,buf .data );
24202478}
24212479}
24222480PQclear (result );
24232481}
24242482
2425- /* print incoming foreign-key references (none if no triggers) */
2426- if (tableinfo .hastriggers )
2483+ /* print incoming foreign-key references */
2484+ if (tableinfo .hastriggers ||
2485+ tableinfo .relkind == RELKIND_PARTITIONED_TABLE )
24272486{
2428- printfPQExpBuffer (& buf ,
2429- "SELECT conname, conrelid::pg_catalog.regclass,\n"
2430- " pg_catalog.pg_get_constraintdef(c.oid, true) as condef\n"
2431- "FROM pg_catalog.pg_constraint c\n"
2432- "WHERE c.confrelid = '%s' AND c.contype = 'f' ORDER BY 1;" ,
2433- oid );
2487+ if (pset .sversion >=120000 )
2488+ {
2489+ printfPQExpBuffer (& buf ,
2490+ "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
2491+ " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
2492+ " FROM pg_catalog.pg_constraint c\n"
2493+ " WHERE confrelid IN (SELECT pg_catalog.pg_partition_ancestors('%s')\n"
2494+ " UNION ALL VALUES ('%s'::pg_catalog.regclass))\n"
2495+ " AND contype = 'f' AND conparentid = 0\n"
2496+ "ORDER BY conname;" ,
2497+ oid ,oid );
2498+ }
2499+ else
2500+ {
2501+ printfPQExpBuffer (& buf ,
2502+ "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
2503+ " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
2504+ " FROM pg_catalog.pg_constraint\n"
2505+ " WHERE confrelid = %s AND contype = 'f'\n"
2506+ "ORDER BY conname;" ,
2507+ oid );
2508+ }
2509+
24342510result = PSQLexec (buf .data );
24352511if (!result )
24362512gotoerror_return ;
@@ -2439,13 +2515,17 @@ describeOneTableDetails(const char *schemaname,
24392515
24402516if (tuples > 0 )
24412517{
2518+ int i_conname = PQfnumber (result ,"conname" ),
2519+ i_ontable = PQfnumber (result ,"ontable" ),
2520+ i_condef = PQfnumber (result ,"condef" );
2521+
24422522printTableAddFooter (& cont ,_ ("Referenced by:" ));
24432523for (i = 0 ;i < tuples ;i ++ )
24442524{
24452525printfPQExpBuffer (& buf ," TABLE \"%s\" CONSTRAINT \"%s\" %s" ,
2446- PQgetvalue (result ,i ,1 ),
2447- PQgetvalue (result ,i ,0 ),
2448- PQgetvalue (result ,i ,2 ));
2526+ PQgetvalue (result ,i ,i_ontable ),
2527+ PQgetvalue (result ,i ,i_conname ),
2528+ PQgetvalue (result ,i ,i_condef ));
24492529
24502530printTableAddFooter (& cont ,buf .data );
24512531}