← Back to Overview

src/bin/psql/describe.c

Coverage: 32/36 lines (88.9%)
Total Lines
36
modified
Covered
32
88.9%
Uncovered
4
11.1%
키보드 네비게이션
permissionsList() lines 1051-1209
Modified Lines Coverage: 0/0 lines (0.0%)
LineHitsSourceCommit
1051 - permissionsList(const char *pattern, bool showSystem) -
1052 - { -
1053 - PQExpBufferData buf; -
1054 - PGresult *res; -
1055 - printQueryOpt myopt = pset.popt; -
1056 - static const bool translate_columns[] = {false, false, true, false, false, false}; -
1057 - -
1058 - initPQExpBuffer(&buf); -
1059 - -
1060 - /* -
1061 - * we ignore indexes and toast tables since they have no meaningful rights -
1062 - */ -
1063 - printfPQExpBuffer(&buf, -
1064 - "SELECT n.nspname as \"%s\",\n" -
1065 - " c.relname as \"%s\",\n" -
1066 - " CASE c.relkind" -
1067 - " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'" -
1068 - " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'" -
1069 - " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'" -
1070 - " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'" -
1071 - " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'" -
1072 - " WHEN " CppAsString2(RELKIND_PROPGRAPH) " THEN '%s'" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1073 - " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'" -
1074 - " END as \"%s\",\n" -
1075 - " ", -
1076 - gettext_noop("Schema"), -
1077 - gettext_noop("Name"), -
1078 - gettext_noop("table"), -
1079 - gettext_noop("view"), -
1080 - gettext_noop("materialized view"), -
1081 - gettext_noop("sequence"), -
1082 - gettext_noop("foreign table"), -
1083 - gettext_noop("property graph"), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1084 - gettext_noop("partitioned table"), -
1085 - gettext_noop("Type")); -
1086 - -
1087 - printACLColumn(&buf, "c.relacl"); -
1088 - -
1089 - /* -
1090 - * The formatting of attacl should match printACLColumn(). However, we -
1091 - * need no special case for an empty attacl, because the backend always -
1092 - * optimizes that back to NULL. -
1093 - */ -
1094 - appendPQExpBuffer(&buf, -
1095 - ",\n pg_catalog.array_to_string(ARRAY(\n" -
1096 - " SELECT attname || E':\\n ' || pg_catalog.array_to_string(attacl, E'\\n ')\n" -
1097 - " FROM pg_catalog.pg_attribute a\n" -
1098 - " WHERE attrelid = c.oid AND NOT attisdropped AND attacl IS NOT NULL\n" -
1099 - " ), E'\\n') AS \"%s\"", -
1100 - gettext_noop("Column privileges")); -
1101 - -
1102 - if (pset.sversion >= 90500 && pset.sversion < 100000) -
1103 - appendPQExpBuffer(&buf, -
1104 - ",\n pg_catalog.array_to_string(ARRAY(\n" -
1105 - " SELECT polname\n" -
1106 - " || CASE WHEN polcmd != '*' THEN\n" -
1107 - " E' (' || polcmd::pg_catalog.text || E'):'\n" -
1108 - " ELSE E':'\n" -
1109 - " END\n" -
1110 - " || CASE WHEN polqual IS NOT NULL THEN\n" -
1111 - " E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n" -
1112 - " ELSE E''\n" -
1113 - " END\n" -
1114 - " || CASE WHEN polwithcheck IS NOT NULL THEN\n" -
1115 - " E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n" -
1116 - " ELSE E''\n" -
1117 - " END" -
1118 - " || CASE WHEN polroles <> '{0}' THEN\n" -
1119 - " E'\\n to: ' || pg_catalog.array_to_string(\n" -
1120 - " ARRAY(\n" -
1121 - " SELECT rolname\n" -
1122 - " FROM pg_catalog.pg_roles\n" -
1123 - " WHERE oid = ANY (polroles)\n" -
1124 - " ORDER BY 1\n" -
1125 - " ), E', ')\n" -
1126 - " ELSE E''\n" -
1127 - " END\n" -
1128 - " FROM pg_catalog.pg_policy pol\n" -
1129 - " WHERE polrelid = c.oid), E'\\n')\n" -
1130 - " AS \"%s\"", -
1131 - gettext_noop("Policies")); -
1132 - -
1133 - if (pset.sversion >= 100000) -
1134 - appendPQExpBuffer(&buf, -
1135 - ",\n pg_catalog.array_to_string(ARRAY(\n" -
1136 - " SELECT polname\n" -
1137 - " || CASE WHEN NOT polpermissive THEN\n" -
1138 - " E' (RESTRICTIVE)'\n" -
1139 - " ELSE '' END\n" -
1140 - " || CASE WHEN polcmd != '*' THEN\n" -
1141 - " E' (' || polcmd::pg_catalog.text || E'):'\n" -
1142 - " ELSE E':'\n" -
1143 - " END\n" -
1144 - " || CASE WHEN polqual IS NOT NULL THEN\n" -
1145 - " E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n" -
1146 - " ELSE E''\n" -
1147 - " END\n" -
1148 - " || CASE WHEN polwithcheck IS NOT NULL THEN\n" -
1149 - " E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n" -
1150 - " ELSE E''\n" -
1151 - " END" -
1152 - " || CASE WHEN polroles <> '{0}' THEN\n" -
1153 - " E'\\n to: ' || pg_catalog.array_to_string(\n" -
1154 - " ARRAY(\n" -
1155 - " SELECT rolname\n" -
1156 - " FROM pg_catalog.pg_roles\n" -
1157 - " WHERE oid = ANY (polroles)\n" -
1158 - " ORDER BY 1\n" -
1159 - " ), E', ')\n" -
1160 - " ELSE E''\n" -
1161 - " END\n" -
1162 - " FROM pg_catalog.pg_policy pol\n" -
1163 - " WHERE polrelid = c.oid), E'\\n')\n" -
1164 - " AS \"%s\"", -
1165 - gettext_noop("Policies")); -
1166 - -
1167 - appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_class c\n" -
1168 - " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" -
1169 - "WHERE c.relkind IN (" -
1170 - CppAsString2(RELKIND_RELATION) "," -
1171 - CppAsString2(RELKIND_VIEW) "," -
1172 - CppAsString2(RELKIND_MATVIEW) "," -
1173 - CppAsString2(RELKIND_SEQUENCE) "," -
1174 - CppAsString2(RELKIND_FOREIGN_TABLE) "," -
1175 - CppAsString2(RELKIND_PROPGRAPH) "," 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1176 - CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n"); -
1177 - -
1178 - if (!showSystem && !pattern) -
1179 - appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" -
1180 - " AND n.nspname <> 'information_schema'\n"); -
1181 - -
1182 - if (!validateSQLNamePattern(&buf, pattern, true, false, -
1183 - "n.nspname", "c.relname", NULL, -
1184 - "pg_catalog.pg_table_is_visible(c.oid)", -
1185 - NULL, 3)) -
1186 - goto error_return; -
1187 - -
1188 - appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); -
1189 - -
1190 - res = PSQLexec(buf.data); -
1191 - if (!res) -
1192 - goto error_return; -
1193 - -
1194 - printfPQExpBuffer(&buf, _("Access privileges")); -
1195 - myopt.title = buf.data; -
1196 - myopt.translate_header = true; -
1197 - myopt.translate_columns = translate_columns; -
1198 - myopt.n_translate_columns = lengthof(translate_columns); -
1199 - -
1200 - printQuery(res, &myopt, pset.queryFout, false, pset.logfile); -
1201 - -
1202 - termPQExpBuffer(&buf); -
1203 - PQclear(res); -
1204 - return true; -
1205 - -
1206 - error_return: -
1207 - termPQExpBuffer(&buf); -
1208 - return false; -
1209 - } -
describeOneTableDetails() lines 1575-3749
Modified Lines Coverage: 25/26 lines (96.2%)
LineHitsSourceCommit
1575 - describeOneTableDetails(const char *schemaname, -
1576 - const char *relationname, -
1577 - const char *oid, -
1578 - bool verbose) -
1579 - { -
1580 - bool retval = false; -
1581 - PQExpBufferData buf; -
1582 - PGresult *res = NULL; -
1583 - printTableOpt myopt = pset.popt.topt; -
1584 - printTableContent cont; -
1585 - bool printTableInitialized = false; -
1586 - int i; -
1587 - char *view_def = NULL; -
1588 - char *headers[12]; -
1589 - PQExpBufferData title; -
1590 - PQExpBufferData tmpbuf; -
1591 - int cols; -
1592 - int attname_col = -1, /* column indexes in "res" */ -
1593 - atttype_col = -1, -
1594 - attrdef_col = -1, -
1595 - attnotnull_col = -1, -
1596 - attcoll_col = -1, -
1597 - attidentity_col = -1, -
1598 - attgenerated_col = -1, -
1599 - isindexkey_col = -1, -
1600 - indexdef_col = -1, -
1601 - fdwopts_col = -1, -
1602 - attstorage_col = -1, -
1603 - attcompression_col = -1, -
1604 - attstattarget_col = -1, -
1605 - attdescr_col = -1; -
1606 - int numrows; -
1607 - struct -
1608 - { -
1609 - int16 checks; -
1610 - char relkind; -
1611 - bool hasindex; -
1612 - bool hasrules; -
1613 - bool hastriggers; -
1614 - bool rowsecurity; -
1615 - bool forcerowsecurity; -
1616 - bool hasoids; -
1617 - bool ispartition; -
1618 - Oid tablespace; -
1619 - char *reloptions; -
1620 - char *reloftype; -
1621 - char relpersistence; -
1622 - char relreplident; -
1623 - char *relam; -
1624 - } tableinfo; -
1625 - bool show_column_details = false; -
1626 - -
1627 - myopt.default_footer = false; -
1628 - /* This output looks confusing in expanded mode. */ -
1629 - myopt.expanded = false; -
1630 - -
1631 - initPQExpBuffer(&buf); -
1632 - initPQExpBuffer(&title); -
1633 - initPQExpBuffer(&tmpbuf); -
1634 - -
1635 - /* Get general table info */ -
1636 - if (pset.sversion >= 120000) -
1637 - { -
1638 - printfPQExpBuffer(&buf, -
1639 - "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " -
1640 - "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, " -
1641 - "false AS relhasoids, c.relispartition, %s, c.reltablespace, " -
1642 - "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, " -
1643 - "c.relpersistence, c.relreplident, am.amname\n" -
1644 - "FROM pg_catalog.pg_class c\n " -
1645 - "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" -
1646 - "LEFT JOIN pg_catalog.pg_am am ON (c.relam = am.oid)\n" -
1647 - "WHERE c.oid = '%s';", -
1648 - (verbose ? -
1649 - "pg_catalog.array_to_string(c.reloptions || " -
1650 - "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" -
1651 - : "''"), -
1652 - oid); -
1653 - } -
1654 - else if (pset.sversion >= 100000) -
1655 - { -
1656 - printfPQExpBuffer(&buf, -
1657 - "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " -
1658 - "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, " -
1659 - "c.relhasoids, c.relispartition, %s, c.reltablespace, " -
1660 - "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, " -
1661 - "c.relpersistence, c.relreplident\n" -
1662 - "FROM pg_catalog.pg_class c\n " -
1663 - "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" -
1664 - "WHERE c.oid = '%s';", -
1665 - (verbose ? -
1666 - "pg_catalog.array_to_string(c.reloptions || " -
1667 - "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" -
1668 - : "''"), -
1669 - oid); -
1670 - } -
1671 - else if (pset.sversion >= 90500) -
1672 - { -
1673 - printfPQExpBuffer(&buf, -
1674 - "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " -
1675 - "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, " -
1676 - "c.relhasoids, false as relispartition, %s, c.reltablespace, " -
1677 - "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, " -
1678 - "c.relpersistence, c.relreplident\n" -
1679 - "FROM pg_catalog.pg_class c\n " -
1680 - "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" -
1681 - "WHERE c.oid = '%s';", -
1682 - (verbose ? -
1683 - "pg_catalog.array_to_string(c.reloptions || " -
1684 - "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" -
1685 - : "''"), -
1686 - oid); -
1687 - } -
1688 - else if (pset.sversion >= 90400) -
1689 - { -
1690 - printfPQExpBuffer(&buf, -
1691 - "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " -
1692 - "c.relhastriggers, false, false, c.relhasoids, " -
1693 - "false as relispartition, %s, c.reltablespace, " -
1694 - "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, " -
1695 - "c.relpersistence, c.relreplident\n" -
1696 - "FROM pg_catalog.pg_class c\n " -
1697 - "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" -
1698 - "WHERE c.oid = '%s';", -
1699 - (verbose ? -
1700 - "pg_catalog.array_to_string(c.reloptions || " -
1701 - "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" -
1702 - : "''"), -
1703 - oid); -
1704 - } -
1705 - else -
1706 - { -
1707 - printfPQExpBuffer(&buf, -
1708 - "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " -
1709 - "c.relhastriggers, false, false, c.relhasoids, " -
1710 - "false as relispartition, %s, c.reltablespace, " -
1711 - "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, " -
1712 - "c.relpersistence\n" -
1713 - "FROM pg_catalog.pg_class c\n " -
1714 - "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" -
1715 - "WHERE c.oid = '%s';", -
1716 - (verbose ? -
1717 - "pg_catalog.array_to_string(c.reloptions || " -
1718 - "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" -
1719 - : "''"), -
1720 - oid); -
1721 - } -
1722 - -
1723 - res = PSQLexec(buf.data); -
1724 - if (!res) -
1725 - goto error_return; -
1726 - -
1727 - /* Did we get anything? */ -
1728 - if (PQntuples(res) == 0) -
1729 - { -
1730 - if (!pset.quiet) -
1731 - pg_log_error("Did not find any relation with OID %s.", oid); -
1732 - goto error_return; -
1733 - } -
1734 - -
1735 - tableinfo.checks = atoi(PQgetvalue(res, 0, 0)); -
1736 - tableinfo.relkind = *(PQgetvalue(res, 0, 1)); -
1737 - tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 2), "t") == 0; -
1738 - tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 3), "t") == 0; -
1739 - tableinfo.hastriggers = strcmp(PQgetvalue(res, 0, 4), "t") == 0; -
1740 - tableinfo.rowsecurity = strcmp(PQgetvalue(res, 0, 5), "t") == 0; -
1741 - tableinfo.forcerowsecurity = strcmp(PQgetvalue(res, 0, 6), "t") == 0; -
1742 - tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 7), "t") == 0; -
1743 - tableinfo.ispartition = strcmp(PQgetvalue(res, 0, 8), "t") == 0; -
1744 - tableinfo.reloptions = pg_strdup(PQgetvalue(res, 0, 9)); -
1745 - tableinfo.tablespace = atooid(PQgetvalue(res, 0, 10)); -
1746 - tableinfo.reloftype = (strcmp(PQgetvalue(res, 0, 11), "") != 0) ? -
1747 - pg_strdup(PQgetvalue(res, 0, 11)) : NULL; -
1748 - tableinfo.relpersistence = *(PQgetvalue(res, 0, 12)); -
1749 - tableinfo.relreplident = (pset.sversion >= 90400) ? -
1750 - *(PQgetvalue(res, 0, 13)) : 'd'; -
1751 - if (pset.sversion >= 120000) -
1752 - tableinfo.relam = PQgetisnull(res, 0, 14) ? -
1753 - NULL : pg_strdup(PQgetvalue(res, 0, 14)); -
1754 - else -
1755 - tableinfo.relam = NULL; -
1756 - PQclear(res); -
1757 - res = NULL; -
1758 - -
1759 - /* -
1760 - * If it's a sequence, deal with it here separately. -
1761 - */ -
1762 - if (tableinfo.relkind == RELKIND_SEQUENCE) -
1763 - { -
1764 - PGresult *result = NULL; -
1765 - printQueryOpt myopt = pset.popt; -
1766 - char *footers[3] = {NULL, NULL, NULL}; -
1767 - -
1768 - if (pset.sversion >= 100000) -
1769 - { -
1770 - printfPQExpBuffer(&buf, -
1771 - "SELECT pg_catalog.format_type(seqtypid, NULL) AS \"%s\",\n" -
1772 - " seqstart AS \"%s\",\n" -
1773 - " seqmin AS \"%s\",\n" -
1774 - " seqmax AS \"%s\",\n" -
1775 - " seqincrement AS \"%s\",\n" -
1776 - " CASE WHEN seqcycle THEN '%s' ELSE '%s' END AS \"%s\",\n" -
1777 - " seqcache AS \"%s\"\n", -
1778 - gettext_noop("Type"), -
1779 - gettext_noop("Start"), -
1780 - gettext_noop("Minimum"), -
1781 - gettext_noop("Maximum"), -
1782 - gettext_noop("Increment"), -
1783 - gettext_noop("yes"), -
1784 - gettext_noop("no"), -
1785 - gettext_noop("Cycles?"), -
1786 - gettext_noop("Cache")); -
1787 - appendPQExpBuffer(&buf, -
1788 - "FROM pg_catalog.pg_sequence\n" -
1789 - "WHERE seqrelid = '%s';", -
1790 - oid); -
1791 - } -
1792 - else -
1793 - { -
1794 - printfPQExpBuffer(&buf, -
1795 - "SELECT 'bigint' AS \"%s\",\n" -
1796 - " start_value AS \"%s\",\n" -
1797 - " min_value AS \"%s\",\n" -
1798 - " max_value AS \"%s\",\n" -
1799 - " increment_by AS \"%s\",\n" -
1800 - " CASE WHEN is_cycled THEN '%s' ELSE '%s' END AS \"%s\",\n" -
1801 - " cache_value AS \"%s\"\n", -
1802 - gettext_noop("Type"), -
1803 - gettext_noop("Start"), -
1804 - gettext_noop("Minimum"), -
1805 - gettext_noop("Maximum"), -
1806 - gettext_noop("Increment"), -
1807 - gettext_noop("yes"), -
1808 - gettext_noop("no"), -
1809 - gettext_noop("Cycles?"), -
1810 - gettext_noop("Cache")); -
1811 - appendPQExpBuffer(&buf, "FROM %s", fmtId(schemaname)); -
1812 - /* must be separate because fmtId isn't reentrant */ -
1813 - appendPQExpBuffer(&buf, ".%s;", fmtId(relationname)); -
1814 - } -
1815 - -
1816 - res = PSQLexec(buf.data); -
1817 - if (!res) -
1818 - goto error_return; -
1819 - -
1820 - /* Get the column that owns this sequence */ -
1821 - printfPQExpBuffer(&buf, "SELECT pg_catalog.quote_ident(nspname) || '.' ||" -
1822 - "\n pg_catalog.quote_ident(relname) || '.' ||" -
1823 - "\n pg_catalog.quote_ident(attname)," -
1824 - "\n d.deptype" -
1825 - "\nFROM pg_catalog.pg_class c" -
1826 - "\nINNER JOIN pg_catalog.pg_depend d ON c.oid=d.refobjid" -
1827 - "\nINNER JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace" -
1828 - "\nINNER JOIN pg_catalog.pg_attribute a ON (" -
1829 - "\n a.attrelid=c.oid AND" -
1830 - "\n a.attnum=d.refobjsubid)" -
1831 - "\nWHERE d.classid='pg_catalog.pg_class'::pg_catalog.regclass" -
1832 - "\n AND d.refclassid='pg_catalog.pg_class'::pg_catalog.regclass" -
1833 - "\n AND d.objid='%s'" -
1834 - "\n AND d.deptype IN ('a', 'i')", -
1835 - oid); -
1836 - -
1837 - result = PSQLexec(buf.data); -
1838 - -
1839 - /* -
1840 - * If we get no rows back, don't show anything (obviously). We should -
1841 - * never get more than one row back, but if we do, just ignore it and -
1842 - * don't print anything. -
1843 - */ -
1844 - if (!result) -
1845 - goto error_return; -
1846 - else if (PQntuples(result) == 1) -
1847 - { -
1848 - switch (PQgetvalue(result, 0, 1)[0]) -
1849 - { -
1850 - case 'a': -
1851 - footers[0] = psprintf(_("Owned by: %s"), -
1852 - PQgetvalue(result, 0, 0)); -
1853 - break; -
1854 - case 'i': -
1855 - footers[0] = psprintf(_("Sequence for identity column: %s"), -
1856 - PQgetvalue(result, 0, 0)); -
1857 - break; -
1858 - } -
1859 - } -
1860 - PQclear(result); -
1861 - -
1862 - /* Print any publications */ -
1863 - if (pset.sversion >= 190000) -
1864 - { -
1865 - printfPQExpBuffer(&buf, "SELECT pubname FROM pg_catalog.pg_publication p" -
1866 - "\nWHERE p.puballsequences" -
1867 - "\n AND pg_catalog.pg_relation_is_publishable('%s')" -
1868 - "\nORDER BY 1", -
1869 - oid); -
1870 - -
1871 - result = PSQLexec(buf.data); -
1872 - if (result) -
1873 - { -
1874 - int nrows = PQntuples(result); -
1875 - -
1876 - if (nrows > 0) -
1877 - { -
1878 - printfPQExpBuffer(&tmpbuf, _("Publications:")); -
1879 - for (i = 0; i < nrows; i++) -
1880 - appendPQExpBuffer(&tmpbuf, "\n \"%s\"", PQgetvalue(result, i, 0)); -
1881 - -
1882 - /* Store in the first available footer slot */ -
1883 - if (footers[0] == NULL) -
1884 - footers[0] = pg_strdup(tmpbuf.data); -
1885 - else -
1886 - footers[1] = pg_strdup(tmpbuf.data); -
1887 - -
1888 - resetPQExpBuffer(&tmpbuf); -
1889 - } -
1890 - -
1891 - PQclear(result); -
1892 - } -
1893 - } -
1894 - -
1895 - if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) -
1896 - printfPQExpBuffer(&title, _("Unlogged sequence \"%s.%s\""), -
1897 - schemaname, relationname); -
1898 - else -
1899 - printfPQExpBuffer(&title, _("Sequence \"%s.%s\""), -
1900 - schemaname, relationname); -
1901 - -
1902 - myopt.footers = footers; -
1903 - myopt.topt.default_footer = false; -
1904 - myopt.title = title.data; -
1905 - myopt.translate_header = true; -
1906 - -
1907 - printQuery(res, &myopt, pset.queryFout, false, pset.logfile); -
1908 - -
1909 - free(footers[0]); -
1910 - free(footers[1]); -
1911 - -
1912 - retval = true; -
1913 - goto error_return; /* not an error, just return early */ -
1914 - } -
1915 - -
1916 - /* 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1917 - * If it's a property graph, deal with it here separately. 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1918 - */ 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1919 1988 if (tableinfo.relkind == RELKIND_PROPGRAPH) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1920 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1921 12 printQueryOpt myopt = pset.popt; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1922 12 char *footers[3] = {NULL, NULL, NULL}; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1923 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1924 12 printfPQExpBuffer(&buf, 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1925 - "SELECT e.pgealias AS \"%s\"," 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1926 - "\n pg_catalog.quote_ident(n.nspname) || '.' ||" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1927 - "\n pg_catalog.quote_ident(c.relname) AS \"%s\"," 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1928 - "\n case e.pgekind when " CppAsString2(PGEKIND_VERTEX) " then 'vertex'" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1929 - "\n when " CppAsString2(PGEKIND_EDGE) " then 'edge' end AS \"%s\"," 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1930 - "\n s.pgealias as \"%s\"," 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1931 - "\n d.pgealias as \"%s\"" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1932 - "\n FROM pg_propgraph_element e" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1933 - "\n INNER JOIN pg_class c ON c.oid = e.pgerelid" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1934 - "\n INNER JOIN pg_namespace n ON c.relnamespace = n.oid" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1935 - "\n LEFT JOIN pg_propgraph_element s ON e.pgesrcvertexid = s.oid" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1936 - "\n LEFT JOIN pg_propgraph_element d ON e.pgedestvertexid = d.oid" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1937 - "\n WHERE e.pgepgid = '%s'" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1938 - "\n ORDER BY e.pgealias", 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1939 - gettext_noop("Element Alias"), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1940 - gettext_noop("Element Table"), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1941 - gettext_noop("Element Kind"), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1942 - gettext_noop("Source Vertex Alias"), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1943 - gettext_noop("Destination Vertex Alias"), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1944 - oid); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1945 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1946 12 res = PSQLexec(buf.data); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1947 12 if (!res) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1948 0 goto error_return; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1949 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1950 12 printfPQExpBuffer(&title, _("Property Graph \"%s.%s\""), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1951 - schemaname, relationname); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1952 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1953 - /* Add property graph definition in verbose mode */ 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1954 12 if (verbose) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1955 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1956 6 PGresult *result; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1957 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1958 6 printfPQExpBuffer(&buf, 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1959 - "SELECT pg_catalog.pg_get_propgraphdef('%s'::pg_catalog.oid);", 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1960 - oid); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1961 6 result = PSQLexec(buf.data); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1962 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1963 6 if (result) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1964 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1965 6 if (PQntuples(result) > 0) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1966 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1967 6 footers[0] = pg_strdup(_("Property graph definition:")); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1968 6 footers[1] = pg_strdup(PQgetvalue(result, 0, 0)); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1969 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1970 6 PQclear(result); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1971 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1972 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1973 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1974 12 myopt.footers = footers; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1975 12 myopt.topt.default_footer = false; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1976 12 myopt.title = title.data; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1977 12 myopt.translate_header = true; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1978 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1979 12 printQuery(res, &myopt, pset.queryFout, false, pset.logfile); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1980 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1981 12 free(footers[0]); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1982 12 free(footers[1]); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1983 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1984 12 retval = true; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1985 12 goto error_return; /* not an error, just return early */ 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1986 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1987 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1988 - /* Identify whether we should print collation, nullable, default vals */ -
1989 - if (tableinfo.relkind == RELKIND_RELATION || -
1990 - tableinfo.relkind == RELKIND_VIEW || -
1991 - tableinfo.relkind == RELKIND_MATVIEW || -
1992 - tableinfo.relkind == RELKIND_FOREIGN_TABLE || -
1993 - tableinfo.relkind == RELKIND_COMPOSITE_TYPE || -
1994 - tableinfo.relkind == RELKIND_PARTITIONED_TABLE) -
1995 - show_column_details = true; -
1996 - -
1997 - /* -
1998 - * Get per-column info -
1999 - * -
2000 - * Since the set of query columns we need varies depending on relkind and -
2001 - * server version, we compute all the column numbers on-the-fly. Column -
2002 - * number variables for columns not fetched are left as -1; this avoids -
2003 - * duplicative test logic below. -
2004 - */ -
2005 - cols = 0; -
2006 - printfPQExpBuffer(&buf, "SELECT a.attname"); -
2007 - attname_col = cols++; -
2008 - appendPQExpBufferStr(&buf, ",\n pg_catalog.format_type(a.atttypid, a.atttypmod)"); -
2009 - atttype_col = cols++; -
2010 - -
2011 - if (show_column_details) -
2012 - { -
2013 - /* use "pretty" mode for expression to avoid excessive parentheses */ -
2014 - appendPQExpBufferStr(&buf, -
2015 - ",\n (SELECT pg_catalog.pg_get_expr(d.adbin, d.adrelid, true)" -
2016 - "\n FROM pg_catalog.pg_attrdef d" -
2017 - "\n WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef)" -
2018 - ",\n a.attnotnull"); -
2019 - attrdef_col = cols++; -
2020 - attnotnull_col = cols++; -
2021 - appendPQExpBufferStr(&buf, ",\n (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t\n" -
2022 - " WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation) AS attcollation"); -
2023 - attcoll_col = cols++; -
2024 - if (pset.sversion >= 100000) -
2025 - appendPQExpBufferStr(&buf, ",\n a.attidentity"); -
2026 - else -
2027 - appendPQExpBufferStr(&buf, ",\n ''::pg_catalog.char AS attidentity"); -
2028 - attidentity_col = cols++; -
2029 - if (pset.sversion >= 120000) -
2030 - appendPQExpBufferStr(&buf, ",\n a.attgenerated"); -
2031 - else -
2032 - appendPQExpBufferStr(&buf, ",\n ''::pg_catalog.char AS attgenerated"); -
2033 - attgenerated_col = cols++; -
2034 - } -
2035 - if (tableinfo.relkind == RELKIND_INDEX || -
2036 - tableinfo.relkind == RELKIND_PARTITIONED_INDEX) -
2037 - { -
2038 - if (pset.sversion >= 110000) -
2039 - { -
2040 - appendPQExpBuffer(&buf, ",\n CASE WHEN a.attnum <= (SELECT i.indnkeyatts FROM pg_catalog.pg_index i WHERE i.indexrelid = '%s') THEN '%s' ELSE '%s' END AS is_key", -
2041 - oid, -
2042 - gettext_noop("yes"), -
2043 - gettext_noop("no")); -
2044 - isindexkey_col = cols++; -
2045 - } -
2046 - appendPQExpBufferStr(&buf, ",\n pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE) AS indexdef"); -
2047 - indexdef_col = cols++; -
2048 - } -
2049 - /* FDW options for foreign table column */ -
2050 - if (tableinfo.relkind == RELKIND_FOREIGN_TABLE) -
2051 - { -
2052 - appendPQExpBufferStr(&buf, ",\n CASE WHEN attfdwoptions IS NULL THEN '' ELSE " -
2053 - " '(' || pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value) FROM " -
2054 - " pg_catalog.pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions"); -
2055 - fdwopts_col = cols++; -
2056 - } -
2057 - if (verbose) -
2058 - { -
2059 - appendPQExpBufferStr(&buf, ",\n a.attstorage"); -
2060 - attstorage_col = cols++; -
2061 - -
2062 - /* compression info, if relevant to relkind */ -
2063 - if (pset.sversion >= 140000 && -
2064 - !pset.hide_compression && -
2065 - (tableinfo.relkind == RELKIND_RELATION || -
2066 - tableinfo.relkind == RELKIND_PARTITIONED_TABLE || -
2067 - tableinfo.relkind == RELKIND_MATVIEW)) -
2068 - { -
2069 - appendPQExpBufferStr(&buf, ",\n a.attcompression AS attcompression"); -
2070 - attcompression_col = cols++; -
2071 - } -
2072 - -
2073 - /* stats target, if relevant to relkind */ -
2074 - if (tableinfo.relkind == RELKIND_RELATION || -
2075 - tableinfo.relkind == RELKIND_INDEX || -
2076 - tableinfo.relkind == RELKIND_PARTITIONED_INDEX || -
2077 - tableinfo.relkind == RELKIND_MATVIEW || -
2078 - tableinfo.relkind == RELKIND_FOREIGN_TABLE || -
2079 - tableinfo.relkind == RELKIND_PARTITIONED_TABLE) -
2080 - { -
2081 - appendPQExpBufferStr(&buf, ",\n CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget"); -
2082 - attstattarget_col = cols++; -
2083 - } -
2084 - -
2085 - /* -
2086 - * In 9.0+, we have column comments for: relations, views, composite -
2087 - * types, and foreign tables (cf. CommentObject() in comment.c). -
2088 - */ -
2089 - if (tableinfo.relkind == RELKIND_RELATION || -
2090 - tableinfo.relkind == RELKIND_VIEW || -
2091 - tableinfo.relkind == RELKIND_MATVIEW || -
2092 - tableinfo.relkind == RELKIND_FOREIGN_TABLE || -
2093 - tableinfo.relkind == RELKIND_COMPOSITE_TYPE || -
2094 - tableinfo.relkind == RELKIND_PARTITIONED_TABLE) -
2095 - { -
2096 - appendPQExpBufferStr(&buf, ",\n pg_catalog.col_description(a.attrelid, a.attnum)"); -
2097 - attdescr_col = cols++; -
2098 - } -
2099 - } -
2100 - -
2101 - appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_attribute a"); -
2102 - appendPQExpBuffer(&buf, "\nWHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped", oid); -
2103 - appendPQExpBufferStr(&buf, "\nORDER BY a.attnum;"); -
2104 - -
2105 - res = PSQLexec(buf.data); -
2106 - if (!res) -
2107 - goto error_return; -
2108 - numrows = PQntuples(res); -
2109 - -
2110 - /* Make title */ -
2111 - switch (tableinfo.relkind) -
2112 - { -
2113 - case RELKIND_RELATION: -
2114 - if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) -
2115 - printfPQExpBuffer(&title, _("Unlogged table \"%s.%s\""), -
2116 - schemaname, relationname); -
2117 - else -
2118 - printfPQExpBuffer(&title, _("Table \"%s.%s\""), -
2119 - schemaname, relationname); -
2120 - break; -
2121 - case RELKIND_VIEW: -
2122 - printfPQExpBuffer(&title, _("View \"%s.%s\""), -
2123 - schemaname, relationname); -
2124 - break; -
2125 - case RELKIND_MATVIEW: -
2126 - printfPQExpBuffer(&title, _("Materialized view \"%s.%s\""), -
2127 - schemaname, relationname); -
2128 - break; -
2129 - case RELKIND_INDEX: -
2130 - if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) -
2131 - printfPQExpBuffer(&title, _("Unlogged index \"%s.%s\""), -
2132 - schemaname, relationname); -
2133 - else -
2134 - printfPQExpBuffer(&title, _("Index \"%s.%s\""), -
2135 - schemaname, relationname); -
2136 - break; -
2137 - case RELKIND_PARTITIONED_INDEX: -
2138 - if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) -
2139 - printfPQExpBuffer(&title, _("Unlogged partitioned index \"%s.%s\""), -
2140 - schemaname, relationname); -
2141 - else -
2142 - printfPQExpBuffer(&title, _("Partitioned index \"%s.%s\""), -
2143 - schemaname, relationname); -
2144 - break; -
2145 - case RELKIND_TOASTVALUE: -
2146 - printfPQExpBuffer(&title, _("TOAST table \"%s.%s\""), -
2147 - schemaname, relationname); -
2148 - break; -
2149 - case RELKIND_COMPOSITE_TYPE: -
2150 - printfPQExpBuffer(&title, _("Composite type \"%s.%s\""), -
2151 - schemaname, relationname); -
2152 - break; -
2153 - case RELKIND_FOREIGN_TABLE: -
2154 - printfPQExpBuffer(&title, _("Foreign table \"%s.%s\""), -
2155 - schemaname, relationname); -
2156 - break; -
2157 - case RELKIND_PARTITIONED_TABLE: -
2158 - if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) -
2159 - printfPQExpBuffer(&title, _("Unlogged partitioned table \"%s.%s\""), -
2160 - schemaname, relationname); -
2161 - else -
2162 - printfPQExpBuffer(&title, _("Partitioned table \"%s.%s\""), -
2163 - schemaname, relationname); -
2164 - break; -
2165 - default: -
2166 - /* untranslated unknown relkind */ -
2167 - printfPQExpBuffer(&title, "?%c? \"%s.%s\"", -
2168 - tableinfo.relkind, schemaname, relationname); -
2169 - break; -
2170 - } -
2171 - -
2172 - /* Fill headers[] with the names of the columns we will output */ -
2173 - cols = 0; -
2174 - headers[cols++] = gettext_noop("Column"); -
2175 - headers[cols++] = gettext_noop("Type"); -
2176 - if (show_column_details) -
2177 - { -
2178 - headers[cols++] = gettext_noop("Collation"); -
2179 - headers[cols++] = gettext_noop("Nullable"); -
2180 - headers[cols++] = gettext_noop("Default"); -
2181 - } -
2182 - if (isindexkey_col >= 0) -
2183 - headers[cols++] = gettext_noop("Key?"); -
2184 - if (indexdef_col >= 0) -
2185 - headers[cols++] = gettext_noop("Definition"); -
2186 - if (fdwopts_col >= 0) -
2187 - headers[cols++] = gettext_noop("FDW options"); -
2188 - if (attstorage_col >= 0) -
2189 - headers[cols++] = gettext_noop("Storage"); -
2190 - if (attcompression_col >= 0) -
2191 - headers[cols++] = gettext_noop("Compression"); -
2192 - if (attstattarget_col >= 0) -
2193 - headers[cols++] = gettext_noop("Stats target"); -
2194 - if (attdescr_col >= 0) -
2195 - headers[cols++] = gettext_noop("Description"); -
2196 - -
2197 - Assert(cols <= lengthof(headers)); -
2198 - -
2199 - printTableInit(&cont, &myopt, title.data, cols, numrows); -
2200 - printTableInitialized = true; -
2201 - -
2202 - for (i = 0; i < cols; i++) -
2203 - printTableAddHeader(&cont, headers[i], true, 'l'); -
2204 - -
2205 - /* Generate table cells to be printed */ -
2206 - for (i = 0; i < numrows; i++) -
2207 - { -
2208 - /* Column */ -
2209 - printTableAddCell(&cont, PQgetvalue(res, i, attname_col), false, false); -
2210 - -
2211 - /* Type */ -
2212 - printTableAddCell(&cont, PQgetvalue(res, i, atttype_col), false, false); -
2213 - -
2214 - /* Collation, Nullable, Default */ -
2215 - if (show_column_details) -
2216 - { -
2217 - char *identity; -
2218 - char *generated; -
2219 - char *default_str; -
2220 - bool mustfree = false; -
2221 - -
2222 - printTableAddCell(&cont, PQgetvalue(res, i, attcoll_col), false, false); -
2223 - -
2224 - printTableAddCell(&cont, -
2225 - strcmp(PQgetvalue(res, i, attnotnull_col), "t") == 0 ? "not null" : "", -
2226 - false, false); -
2227 - -
2228 - identity = PQgetvalue(res, i, attidentity_col); -
2229 - generated = PQgetvalue(res, i, attgenerated_col); -
2230 - -
2231 - if (identity[0] == ATTRIBUTE_IDENTITY_ALWAYS) -
2232 - default_str = "generated always as identity"; -
2233 - else if (identity[0] == ATTRIBUTE_IDENTITY_BY_DEFAULT) -
2234 - default_str = "generated by default as identity"; -
2235 - else if (generated[0] == ATTRIBUTE_GENERATED_STORED) -
2236 - { -
2237 - default_str = psprintf("generated always as (%s) stored", -
2238 - PQgetvalue(res, i, attrdef_col)); -
2239 - mustfree = true; -
2240 - } -
2241 - else if (generated[0] == ATTRIBUTE_GENERATED_VIRTUAL) -
2242 - { -
2243 - default_str = psprintf("generated always as (%s)", -
2244 - PQgetvalue(res, i, attrdef_col)); -
2245 - mustfree = true; -
2246 - } -
2247 - else -
2248 - default_str = PQgetvalue(res, i, attrdef_col); -
2249 - -
2250 - printTableAddCell(&cont, default_str, false, mustfree); -
2251 - } -
2252 - -
2253 - /* Info for index columns */ -
2254 - if (isindexkey_col >= 0) -
2255 - printTableAddCell(&cont, PQgetvalue(res, i, isindexkey_col), true, false); -
2256 - if (indexdef_col >= 0) -
2257 - printTableAddCell(&cont, PQgetvalue(res, i, indexdef_col), false, false); -
2258 - -
2259 - /* FDW options for foreign table columns */ -
2260 - if (fdwopts_col >= 0) -
2261 - printTableAddCell(&cont, PQgetvalue(res, i, fdwopts_col), false, false); -
2262 - -
2263 - /* Storage mode, if relevant */ -
2264 - if (attstorage_col >= 0) -
2265 - { -
2266 - char *storage = PQgetvalue(res, i, attstorage_col); -
2267 - -
2268 - /* these strings are literal in our syntax, so not translated. */ -
2269 - printTableAddCell(&cont, (storage[0] == TYPSTORAGE_PLAIN ? "plain" : -
2270 - (storage[0] == TYPSTORAGE_MAIN ? "main" : -
2271 - (storage[0] == TYPSTORAGE_EXTENDED ? "extended" : -
2272 - (storage[0] == TYPSTORAGE_EXTERNAL ? "external" : -
2273 - "???")))), -
2274 - false, false); -
2275 - } -
2276 - -
2277 - /* Column compression, if relevant */ -
2278 - if (attcompression_col >= 0) -
2279 - { -
2280 - char *compression = PQgetvalue(res, i, attcompression_col); -
2281 - -
2282 - /* these strings are literal in our syntax, so not translated. */ -
2283 - printTableAddCell(&cont, (compression[0] == 'p' ? "pglz" : -
2284 - (compression[0] == 'l' ? "lz4" : -
2285 - (compression[0] == '\0' ? "" : -
2286 - "???"))), -
2287 - false, false); -
2288 - } -
2289 - -
2290 - /* Statistics target, if the relkind supports this feature */ -
2291 - if (attstattarget_col >= 0) -
2292 - printTableAddCell(&cont, PQgetvalue(res, i, attstattarget_col), -
2293 - false, false); -
2294 - -
2295 - /* Column comments, if the relkind supports this feature */ -
2296 - if (attdescr_col >= 0) -
2297 - printTableAddCell(&cont, PQgetvalue(res, i, attdescr_col), -
2298 - false, false); -
2299 - } -
2300 - -
2301 - /* Make footers */ -
2302 - -
2303 - if (tableinfo.ispartition) -
2304 - { -
2305 - /* Footer information for a partition child table */ -
2306 - PGresult *result; -
2307 - -
2308 - printfPQExpBuffer(&buf, -
2309 - "SELECT inhparent::pg_catalog.regclass,\n" -
2310 - " pg_catalog.pg_get_expr(c.relpartbound, c.oid),\n "); -
2311 - -
2312 - appendPQExpBufferStr(&buf, -
2313 - pset.sversion >= 140000 ? "inhdetachpending" : -
2314 - "false as inhdetachpending"); -
2315 - -
2316 - /* If verbose, also request the partition constraint definition */ -
2317 - if (verbose) -
2318 - appendPQExpBufferStr(&buf, -
2319 - ",\n pg_catalog.pg_get_partition_constraintdef(c.oid)"); -
2320 - appendPQExpBuffer(&buf, -
2321 - "\nFROM pg_catalog.pg_class c" -
2322 - " JOIN pg_catalog.pg_inherits i" -
2323 - " ON c.oid = inhrelid" -
2324 - "\nWHERE c.oid = '%s';", oid); -
2325 - result = PSQLexec(buf.data); -
2326 - if (!result) -
2327 - goto error_return; -
2328 - -
2329 - if (PQntuples(result) > 0) -
2330 - { -
2331 - char *parent_name = PQgetvalue(result, 0, 0); -
2332 - char *partdef = PQgetvalue(result, 0, 1); -
2333 - char *detached = PQgetvalue(result, 0, 2); -
2334 - -
2335 - printfPQExpBuffer(&tmpbuf, _("Partition of: %s %s%s"), parent_name, -
2336 - partdef, -
2337 - strcmp(detached, "t") == 0 ? " DETACH PENDING" : ""); -
2338 - printTableAddFooter(&cont, tmpbuf.data); -
2339 - -
2340 - if (verbose) -
2341 - { -
2342 - char *partconstraintdef = NULL; -
2343 - -
2344 - if (!PQgetisnull(result, 0, 3)) -
2345 - partconstraintdef = PQgetvalue(result, 0, 3); -
2346 - /* If there isn't any constraint, show that explicitly */ -
2347 - if (partconstraintdef == NULL || partconstraintdef[0] == '\0') -
2348 - printfPQExpBuffer(&tmpbuf, _("No partition constraint")); -
2349 - else -
2350 - printfPQExpBuffer(&tmpbuf, _("Partition constraint: %s"), -
2351 - partconstraintdef); -
2352 - printTableAddFooter(&cont, tmpbuf.data); -
2353 - } -
2354 - } -
2355 - PQclear(result); -
2356 - } -
2357 - -
2358 - if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE) -
2359 - { -
2360 - /* Footer information for a partitioned table (partitioning parent) */ -
2361 - PGresult *result; -
2362 - -
2363 - printfPQExpBuffer(&buf, -
2364 - "SELECT pg_catalog.pg_get_partkeydef('%s'::pg_catalog.oid);", -
2365 - oid); -
2366 - result = PSQLexec(buf.data); -
2367 - if (!result) -
2368 - goto error_return; -
2369 - -
2370 - if (PQntuples(result) == 1) -
2371 - { -
2372 - char *partkeydef = PQgetvalue(result, 0, 0); -
2373 - -
2374 - printfPQExpBuffer(&tmpbuf, _("Partition key: %s"), partkeydef); -
2375 - printTableAddFooter(&cont, tmpbuf.data); -
2376 - } -
2377 - PQclear(result); -
2378 - } -
2379 - -
2380 - if (tableinfo.relkind == RELKIND_TOASTVALUE) -
2381 - { -
2382 - /* For a TOAST table, print name of owning table */ -
2383 - PGresult *result; -
2384 - -
2385 - printfPQExpBuffer(&buf, -
2386 - "SELECT n.nspname, c.relname\n" -
2387 - "FROM pg_catalog.pg_class c" -
2388 - " JOIN pg_catalog.pg_namespace n" -
2389 - " ON n.oid = c.relnamespace\n" -
2390 - "WHERE reltoastrelid = '%s';", oid); -
2391 - result = PSQLexec(buf.data); -
2392 - if (!result) -
2393 - goto error_return; -
2394 - -
2395 - if (PQntuples(result) == 1) -
2396 - { -
2397 - char *schemaname = PQgetvalue(result, 0, 0); -
2398 - char *relname = PQgetvalue(result, 0, 1); -
2399 - -
2400 - printfPQExpBuffer(&tmpbuf, _("Owning table: \"%s.%s\""), -
2401 - schemaname, relname); -
2402 - printTableAddFooter(&cont, tmpbuf.data); -
2403 - } -
2404 - PQclear(result); -
2405 - } -
2406 - -
2407 - if (tableinfo.relkind == RELKIND_INDEX || -
2408 - tableinfo.relkind == RELKIND_PARTITIONED_INDEX) -
2409 - { -
2410 - /* Footer information about an index */ -
2411 - PGresult *result; -
2412 - -
2413 - printfPQExpBuffer(&buf, -
2414 - "SELECT i.indisunique, i.indisprimary, i.indisclustered, " -
2415 - "i.indisvalid,\n" -
2416 - " (NOT i.indimmediate) AND " -
2417 - "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint " -
2418 - "WHERE conrelid = i.indrelid AND " -
2419 - "conindid = i.indexrelid AND " -
2420 - "contype IN (" CppAsString2(CONSTRAINT_PRIMARY) "," -
2421 - CppAsString2(CONSTRAINT_UNIQUE) "," -
2422 - CppAsString2(CONSTRAINT_EXCLUSION) ") AND " -
2423 - "condeferrable) AS condeferrable,\n" -
2424 - " (NOT i.indimmediate) AND " -
2425 - "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint " -
2426 - "WHERE conrelid = i.indrelid AND " -
2427 - "conindid = i.indexrelid AND " -
2428 - "contype IN (" CppAsString2(CONSTRAINT_PRIMARY) "," -
2429 - CppAsString2(CONSTRAINT_UNIQUE) "," -
2430 - CppAsString2(CONSTRAINT_EXCLUSION) ") AND " -
2431 - "condeferred) AS condeferred,\n"); -
2432 - -
2433 - if (pset.sversion >= 90400) -
2434 - appendPQExpBufferStr(&buf, "i.indisreplident,\n"); -
2435 - else -
2436 - appendPQExpBufferStr(&buf, "false AS indisreplident,\n"); -
2437 - -
2438 - if (pset.sversion >= 150000) -
2439 - appendPQExpBufferStr(&buf, "i.indnullsnotdistinct,\n"); -
2440 - else -
2441 - appendPQExpBufferStr(&buf, "false AS indnullsnotdistinct,\n"); -
2442 - -
2443 - appendPQExpBuffer(&buf, " a.amname, c2.relname, " -
2444 - "pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n" -
2445 - "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n" -
2446 - "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n" -
2447 - "AND i.indrelid = c2.oid;", -
2448 - oid); -
2449 - -
2450 - result = PSQLexec(buf.data); -
2451 - if (!result) -
2452 - goto error_return; -
2453 - else if (PQntuples(result) != 1) -
2454 - { -
2455 - PQclear(result); -
2456 - goto error_return; -
2457 - } -
2458 - else -
2459 - { -
2460 - char *indisunique = PQgetvalue(result, 0, 0); -
2461 - char *indisprimary = PQgetvalue(result, 0, 1); -
2462 - char *indisclustered = PQgetvalue(result, 0, 2); -
2463 - char *indisvalid = PQgetvalue(result, 0, 3); -
2464 - char *deferrable = PQgetvalue(result, 0, 4); -
2465 - char *deferred = PQgetvalue(result, 0, 5); -
2466 - char *indisreplident = PQgetvalue(result, 0, 6); -
2467 - char *indnullsnotdistinct = PQgetvalue(result, 0, 7); -
2468 - char *indamname = PQgetvalue(result, 0, 8); -
2469 - char *indtable = PQgetvalue(result, 0, 9); -
2470 - char *indpred = PQgetvalue(result, 0, 10); -
2471 - -
2472 - if (strcmp(indisprimary, "t") == 0) -
2473 - printfPQExpBuffer(&tmpbuf, _("primary key, ")); -
2474 - else if (strcmp(indisunique, "t") == 0) -
2475 - { -
2476 - printfPQExpBuffer(&tmpbuf, _("unique")); -
2477 - if (strcmp(indnullsnotdistinct, "t") == 0) -
2478 - appendPQExpBufferStr(&tmpbuf, _(" nulls not distinct")); -
2479 - appendPQExpBufferStr(&tmpbuf, _(", ")); -
2480 - } -
2481 - else -
2482 - resetPQExpBuffer(&tmpbuf); -
2483 - appendPQExpBuffer(&tmpbuf, "%s, ", indamname); -
2484 - -
2485 - /* we assume here that index and table are in same schema */ -
2486 - appendPQExpBuffer(&tmpbuf, _("for table \"%s.%s\""), -
2487 - schemaname, indtable); -
2488 - -
2489 - if (strlen(indpred)) -
2490 - appendPQExpBuffer(&tmpbuf, _(", predicate (%s)"), indpred); -
2491 - -
2492 - if (strcmp(indisclustered, "t") == 0) -
2493 - appendPQExpBufferStr(&tmpbuf, _(", clustered")); -
2494 - -
2495 - if (strcmp(indisvalid, "t") != 0) -
2496 - appendPQExpBufferStr(&tmpbuf, _(", invalid")); -
2497 - -
2498 - if (strcmp(deferrable, "t") == 0) -
2499 - appendPQExpBufferStr(&tmpbuf, _(", deferrable")); -
2500 - -
2501 - if (strcmp(deferred, "t") == 0) -
2502 - appendPQExpBufferStr(&tmpbuf, _(", initially deferred")); -
2503 - -
2504 - if (strcmp(indisreplident, "t") == 0) -
2505 - appendPQExpBufferStr(&tmpbuf, _(", replica identity")); -
2506 - -
2507 - printTableAddFooter(&cont, tmpbuf.data); -
2508 - -
2509 - /* -
2510 - * If it's a partitioned index, we'll print the tablespace below -
2511 - */ -
2512 - if (tableinfo.relkind == RELKIND_INDEX) -
2513 - add_tablespace_footer(&cont, tableinfo.relkind, -
2514 - tableinfo.tablespace, true); -
2515 - } -
2516 - -
2517 - PQclear(result); -
2518 - } -
2519 - /* If you add relkinds here, see also "Finish printing..." stanza below */ -
2520 - else if (tableinfo.relkind == RELKIND_RELATION || -
2521 - tableinfo.relkind == RELKIND_MATVIEW || -
2522 - tableinfo.relkind == RELKIND_FOREIGN_TABLE || -
2523 - tableinfo.relkind == RELKIND_PARTITIONED_TABLE || -
2524 - tableinfo.relkind == RELKIND_PARTITIONED_INDEX || -
2525 - tableinfo.relkind == RELKIND_TOASTVALUE) -
2526 - { -
2527 - /* Footer information about a table */ -
2528 - PGresult *result = NULL; -
2529 - int tuples = 0; -
2530 - -
2531 - /* print indexes */ -
2532 - if (tableinfo.hasindex) -
2533 - { -
2534 - printfPQExpBuffer(&buf, -
2535 - "SELECT c2.relname, i.indisprimary, i.indisunique, " -
2536 - "i.indisclustered, i.indisvalid, " -
2537 - "pg_catalog.pg_get_indexdef(i.indexrelid, 0, true),\n " -
2538 - "pg_catalog.pg_get_constraintdef(con.oid, true), " -
2539 - "contype, condeferrable, condeferred"); -
2540 - if (pset.sversion >= 90400) -
2541 - appendPQExpBufferStr(&buf, ", i.indisreplident"); -
2542 - else -
2543 - appendPQExpBufferStr(&buf, ", false AS indisreplident"); -
2544 - appendPQExpBufferStr(&buf, ", c2.reltablespace"); -
2545 - if (pset.sversion >= 180000) -
2546 - appendPQExpBufferStr(&buf, ", con.conperiod"); -
2547 - else -
2548 - appendPQExpBufferStr(&buf, ", false AS conperiod"); -
2549 - appendPQExpBuffer(&buf, -
2550 - "\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n" -
2551 - " LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN (" -
2552 - CppAsString2(CONSTRAINT_PRIMARY) "," -
2553 - CppAsString2(CONSTRAINT_UNIQUE) "," -
2554 - CppAsString2(CONSTRAINT_EXCLUSION) "))\n" -
2555 - "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n" -
2556 - "ORDER BY i.indisprimary DESC, c2.relname;", -
2557 - oid); -
2558 - result = PSQLexec(buf.data); -
2559 - if (!result) -
2560 - goto error_return; -
2561 - else -
2562 - tuples = PQntuples(result); -
2563 - -
2564 - if (tuples > 0) -
2565 - { -
2566 - printTableAddFooter(&cont, _("Indexes:")); -
2567 - for (i = 0; i < tuples; i++) -
2568 - { -
2569 - /* untranslated index name */ -
2570 - printfPQExpBuffer(&buf, " \"%s\"", -
2571 - PQgetvalue(result, i, 0)); -
2572 - -
2573 - /* -
2574 - * If exclusion constraint or PK/UNIQUE constraint WITHOUT -
2575 - * OVERLAPS, print the constraintdef -
2576 - */ -
2577 - if (strcmp(PQgetvalue(result, i, 7), "x") == 0 || -
2578 - strcmp(PQgetvalue(result, i, 12), "t") == 0) -
2579 - { -
2580 - appendPQExpBuffer(&buf, " %s", -
2581 - PQgetvalue(result, i, 6)); -
2582 - } -
2583 - else -
2584 - { -
2585 - const char *indexdef; -
2586 - const char *usingpos; -
2587 - -
2588 - /* Label as primary key or unique (but not both) */ -
2589 - if (strcmp(PQgetvalue(result, i, 1), "t") == 0) -
2590 - appendPQExpBufferStr(&buf, " PRIMARY KEY,"); -
2591 - else if (strcmp(PQgetvalue(result, i, 2), "t") == 0) -
2592 - { -
2593 - if (strcmp(PQgetvalue(result, i, 7), "u") == 0) -
2594 - appendPQExpBufferStr(&buf, " UNIQUE CONSTRAINT,"); -
2595 - else -
2596 - appendPQExpBufferStr(&buf, " UNIQUE,"); -
2597 - } -
2598 - -
2599 - /* Everything after "USING" is echoed verbatim */ -
2600 - indexdef = PQgetvalue(result, i, 5); -
2601 - usingpos = strstr(indexdef, " USING "); -
2602 - if (usingpos) -
2603 - indexdef = usingpos + 7; -
2604 - appendPQExpBuffer(&buf, " %s", indexdef); -
2605 - -
2606 - /* Need these for deferrable PK/UNIQUE indexes */ -
2607 - if (strcmp(PQgetvalue(result, i, 8), "t") == 0) -
2608 - appendPQExpBufferStr(&buf, " DEFERRABLE"); -
2609 - -
2610 - if (strcmp(PQgetvalue(result, i, 9), "t") == 0) -
2611 - appendPQExpBufferStr(&buf, " INITIALLY DEFERRED"); -
2612 - } -
2613 - -
2614 - /* Add these for all cases */ -
2615 - if (strcmp(PQgetvalue(result, i, 3), "t") == 0) -
2616 - appendPQExpBufferStr(&buf, " CLUSTER"); -
2617 - -
2618 - if (strcmp(PQgetvalue(result, i, 4), "t") != 0) -
2619 - appendPQExpBufferStr(&buf, " INVALID"); -
2620 - -
2621 - if (strcmp(PQgetvalue(result, i, 10), "t") == 0) -
2622 - appendPQExpBufferStr(&buf, " REPLICA IDENTITY"); -
2623 - -
2624 - printTableAddFooter(&cont, buf.data); -
2625 - -
2626 - /* Print tablespace of the index on the same line */ -
2627 - add_tablespace_footer(&cont, RELKIND_INDEX, -
2628 - atooid(PQgetvalue(result, i, 11)), -
2629 - false); -
2630 - } -
2631 - } -
2632 - PQclear(result); -
2633 - } -
2634 - -
2635 - /* print table (and column) check constraints */ -
2636 - if (tableinfo.checks) -
2637 - { -
2638 - printfPQExpBuffer(&buf, -
2639 - "SELECT r.conname, " -
2640 - "pg_catalog.pg_get_constraintdef(r.oid, true)\n" -
2641 - "FROM pg_catalog.pg_constraint r\n" -
2642 - "WHERE r.conrelid = '%s' " -
2643 - "AND r.contype = " CppAsString2(CONSTRAINT_CHECK) "\n" -
2644 - "ORDER BY 1;", -
2645 - oid); -
2646 - result = PSQLexec(buf.data); -
2647 - if (!result) -
2648 - goto error_return; -
2649 - else -
2650 - tuples = PQntuples(result); -
2651 - -
2652 - if (tuples > 0) -
2653 - { -
2654 - printTableAddFooter(&cont, _("Check constraints:")); -
2655 - for (i = 0; i < tuples; i++) -
2656 - { -
2657 - /* untranslated constraint name and def */ -
2658 - printfPQExpBuffer(&buf, " \"%s\" %s", -
2659 - PQgetvalue(result, i, 0), -
2660 - PQgetvalue(result, i, 1)); -
2661 - -
2662 - printTableAddFooter(&cont, buf.data); -
2663 - } -
2664 - } -
2665 - PQclear(result); -
2666 - } -
2667 - -
2668 - /* Print foreign-key constraints */ -
2669 - if (pset.sversion >= 120000 && -
2670 - (tableinfo.ispartition || tableinfo.relkind == RELKIND_PARTITIONED_TABLE)) -
2671 - { -
2672 - /* -
2673 - * Put the constraints defined in this table first, followed by -
2674 - * the constraints defined in ancestor partitioned tables. -
2675 - */ -
2676 - printfPQExpBuffer(&buf, -
2677 - "SELECT conrelid = '%s'::pg_catalog.regclass AS sametable,\n" -
2678 - " conname,\n" -
2679 - " pg_catalog.pg_get_constraintdef(oid, true) AS condef,\n" -
2680 - " conrelid::pg_catalog.regclass AS ontable\n" -
2681 - " FROM pg_catalog.pg_constraint,\n" -
2682 - " pg_catalog.pg_partition_ancestors('%s')\n" -
2683 - " WHERE conrelid = relid AND contype = " CppAsString2(CONSTRAINT_FOREIGN) " AND conparentid = 0\n" -
2684 - "ORDER BY sametable DESC, conname;", -
2685 - oid, oid); -
2686 - } -
2687 - else -
2688 - { -
2689 - printfPQExpBuffer(&buf, -
2690 - "SELECT true as sametable, conname,\n" -
2691 - " pg_catalog.pg_get_constraintdef(r.oid, true) as condef,\n" -
2692 - " conrelid::pg_catalog.regclass AS ontable\n" -
2693 - "FROM pg_catalog.pg_constraint r\n" -
2694 - "WHERE r.conrelid = '%s' AND r.contype = " CppAsString2(CONSTRAINT_FOREIGN) "\n", -
2695 - oid); -
2696 - -
2697 - if (pset.sversion >= 120000) -
2698 - appendPQExpBufferStr(&buf, " AND conparentid = 0\n"); -
2699 - appendPQExpBufferStr(&buf, "ORDER BY conname"); -
2700 - } -
2701 - -
2702 - result = PSQLexec(buf.data); -
2703 - if (!result) -
2704 - goto error_return; -
2705 - else -
2706 - tuples = PQntuples(result); -
2707 - -
2708 - if (tuples > 0) -
2709 - { -
2710 - int i_sametable = PQfnumber(result, "sametable"), -
2711 - i_conname = PQfnumber(result, "conname"), -
2712 - i_condef = PQfnumber(result, "condef"), -
2713 - i_ontable = PQfnumber(result, "ontable"); -
2714 - -
2715 - printTableAddFooter(&cont, _("Foreign-key constraints:")); -
2716 - for (i = 0; i < tuples; i++) -
2717 - { -
2718 - /* -
2719 - * Print untranslated constraint name and definition. Use a -
2720 - * "TABLE tab" prefix when the constraint is defined in a -
2721 - * parent partitioned table. -
2722 - */ -
2723 - if (strcmp(PQgetvalue(result, i, i_sametable), "f") == 0) -
2724 - printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s", -
2725 - PQgetvalue(result, i, i_ontable), -
2726 - PQgetvalue(result, i, i_conname), -
2727 - PQgetvalue(result, i, i_condef)); -
2728 - else -
2729 - printfPQExpBuffer(&buf, " \"%s\" %s", -
2730 - PQgetvalue(result, i, i_conname), -
2731 - PQgetvalue(result, i, i_condef)); -
2732 - -
2733 - printTableAddFooter(&cont, buf.data); -
2734 - } -
2735 - } -
2736 - PQclear(result); -
2737 - -
2738 - /* print incoming foreign-key references */ -
2739 - if (pset.sversion >= 120000) -
2740 - { -
2741 - printfPQExpBuffer(&buf, -
2742 - "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n" -
2743 - " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n" -
2744 - " FROM pg_catalog.pg_constraint c\n" -
2745 - " WHERE confrelid IN (SELECT pg_catalog.pg_partition_ancestors('%s')\n" -
2746 - " UNION ALL VALUES ('%s'::pg_catalog.regclass))\n" -
2747 - " AND contype = " CppAsString2(CONSTRAINT_FOREIGN) " AND conparentid = 0\n" -
2748 - "ORDER BY conname;", -
2749 - oid, oid); -
2750 - } -
2751 - else -
2752 - { -
2753 - printfPQExpBuffer(&buf, -
2754 - "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n" -
2755 - " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n" -
2756 - " FROM pg_catalog.pg_constraint\n" -
2757 - " WHERE confrelid = %s AND contype = " CppAsString2(CONSTRAINT_FOREIGN) "\n" -
2758 - "ORDER BY conname;", -
2759 - oid); -
2760 - } -
2761 - -
2762 - result = PSQLexec(buf.data); -
2763 - if (!result) -
2764 - goto error_return; -
2765 - else -
2766 - tuples = PQntuples(result); -
2767 - -
2768 - if (tuples > 0) -
2769 - { -
2770 - int i_conname = PQfnumber(result, "conname"), -
2771 - i_ontable = PQfnumber(result, "ontable"), -
2772 - i_condef = PQfnumber(result, "condef"); -
2773 - -
2774 - printTableAddFooter(&cont, _("Referenced by:")); -
2775 - for (i = 0; i < tuples; i++) -
2776 - { -
2777 - printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s", -
2778 - PQgetvalue(result, i, i_ontable), -
2779 - PQgetvalue(result, i, i_conname), -
2780 - PQgetvalue(result, i, i_condef)); -
2781 - -
2782 - printTableAddFooter(&cont, buf.data); -
2783 - } -
2784 - } -
2785 - PQclear(result); -
2786 - -
2787 - /* print any row-level policies */ -
2788 - if (pset.sversion >= 90500) -
2789 - { -
2790 - printfPQExpBuffer(&buf, "SELECT pol.polname,"); -
2791 - if (pset.sversion >= 100000) -
2792 - appendPQExpBufferStr(&buf, -
2793 - " pol.polpermissive,\n"); -
2794 - else -
2795 - appendPQExpBufferStr(&buf, -
2796 - " 't' as polpermissive,\n"); -
2797 - appendPQExpBuffer(&buf, -
2798 - " CASE WHEN pol.polroles = '{0}' THEN NULL ELSE pg_catalog.array_to_string(array(select rolname from pg_catalog.pg_roles where oid = any (pol.polroles) order by 1),',') END,\n" -
2799 - " pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n" -
2800 - " pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n" -
2801 - " CASE pol.polcmd\n" -
2802 - " WHEN 'r' THEN 'SELECT'\n" -
2803 - " WHEN 'a' THEN 'INSERT'\n" -
2804 - " WHEN 'w' THEN 'UPDATE'\n" -
2805 - " WHEN 'd' THEN 'DELETE'\n" -
2806 - " END AS cmd\n" -
2807 - "FROM pg_catalog.pg_policy pol\n" -
2808 - "WHERE pol.polrelid = '%s' ORDER BY 1;", -
2809 - oid); -
2810 - -
2811 - result = PSQLexec(buf.data); -
2812 - if (!result) -
2813 - goto error_return; -
2814 - else -
2815 - tuples = PQntuples(result); -
2816 - -
2817 - /* -
2818 - * Handle cases where RLS is enabled and there are policies, or -
2819 - * there aren't policies, or RLS isn't enabled but there are -
2820 - * policies -
2821 - */ -
2822 - if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples > 0) -
2823 - printTableAddFooter(&cont, _("Policies:")); -
2824 - -
2825 - if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples > 0) -
2826 - printTableAddFooter(&cont, _("Policies (forced row security enabled):")); -
2827 - -
2828 - if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples == 0) -
2829 - printTableAddFooter(&cont, _("Policies (row security enabled): (none)")); -
2830 - -
2831 - if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples == 0) -
2832 - printTableAddFooter(&cont, _("Policies (forced row security enabled): (none)")); -
2833 - -
2834 - if (!tableinfo.rowsecurity && tuples > 0) -
2835 - printTableAddFooter(&cont, _("Policies (row security disabled):")); -
2836 - -
2837 - /* Might be an empty set - that's ok */ -
2838 - for (i = 0; i < tuples; i++) -
2839 - { -
2840 - printfPQExpBuffer(&buf, " POLICY \"%s\"", -
2841 - PQgetvalue(result, i, 0)); -
2842 - -
2843 - if (*(PQgetvalue(result, i, 1)) == 'f') -
2844 - appendPQExpBufferStr(&buf, " AS RESTRICTIVE"); -
2845 - -
2846 - if (!PQgetisnull(result, i, 5)) -
2847 - appendPQExpBuffer(&buf, " FOR %s", -
2848 - PQgetvalue(result, i, 5)); -
2849 - -
2850 - if (!PQgetisnull(result, i, 2)) -
2851 - { -
2852 - appendPQExpBuffer(&buf, "\n TO %s", -
2853 - PQgetvalue(result, i, 2)); -
2854 - } -
2855 - -
2856 - if (!PQgetisnull(result, i, 3)) -
2857 - appendPQExpBuffer(&buf, "\n USING (%s)", -
2858 - PQgetvalue(result, i, 3)); -
2859 - -
2860 - if (!PQgetisnull(result, i, 4)) -
2861 - appendPQExpBuffer(&buf, "\n WITH CHECK (%s)", -
2862 - PQgetvalue(result, i, 4)); -
2863 - -
2864 - printTableAddFooter(&cont, buf.data); -
2865 - } -
2866 - PQclear(result); -
2867 - } -
2868 - -
2869 - /* print any extended statistics */ -
2870 - if (pset.sversion >= 140000) -
2871 - { -
2872 - printfPQExpBuffer(&buf, -
2873 - "SELECT oid, " -
2874 - "stxrelid::pg_catalog.regclass, " -
2875 - "stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS nsp, " -
2876 - "stxname,\n" -
2877 - "pg_catalog.pg_get_statisticsobjdef_columns(oid) AS columns,\n" -
2878 - " " CppAsString2(STATS_EXT_NDISTINCT) " = any(stxkind) AS ndist_enabled,\n" -
2879 - " " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(stxkind) AS deps_enabled,\n" -
2880 - " " CppAsString2(STATS_EXT_MCV) " = any(stxkind) AS mcv_enabled,\n" -
2881 - "stxstattarget\n" -
2882 - "FROM pg_catalog.pg_statistic_ext\n" -
2883 - "WHERE stxrelid = '%s'\n" -
2884 - "ORDER BY nsp, stxname;", -
2885 - oid); -
2886 - -
2887 - result = PSQLexec(buf.data); -
2888 - if (!result) -
2889 - goto error_return; -
2890 - else -
2891 - tuples = PQntuples(result); -
2892 - -
2893 - if (tuples > 0) -
2894 - { -
2895 - printTableAddFooter(&cont, _("Statistics objects:")); -
2896 - -
2897 - for (i = 0; i < tuples; i++) -
2898 - { -
2899 - bool gotone = false; -
2900 - bool has_ndistinct; -
2901 - bool has_dependencies; -
2902 - bool has_mcv; -
2903 - bool has_all; -
2904 - bool has_some; -
2905 - -
2906 - has_ndistinct = (strcmp(PQgetvalue(result, i, 5), "t") == 0); -
2907 - has_dependencies = (strcmp(PQgetvalue(result, i, 6), "t") == 0); -
2908 - has_mcv = (strcmp(PQgetvalue(result, i, 7), "t") == 0); -
2909 - -
2910 - printfPQExpBuffer(&buf, " "); -
2911 - -
2912 - /* statistics object name (qualified with namespace) */ -
2913 - appendPQExpBuffer(&buf, "\"%s.%s\"", -
2914 - PQgetvalue(result, i, 2), -
2915 - PQgetvalue(result, i, 3)); -
2916 - -
2917 - /* -
2918 - * When printing kinds we ignore expression statistics, -
2919 - * which are used only internally and can't be specified -
2920 - * by user. We don't print the kinds when none are -
2921 - * specified (in which case it has to be statistics on a -
2922 - * single expr) or when all are specified (in which case -
2923 - * we assume it's expanded by CREATE STATISTICS). -
2924 - */ -
2925 - has_all = (has_ndistinct && has_dependencies && has_mcv); -
2926 - has_some = (has_ndistinct || has_dependencies || has_mcv); -
2927 - -
2928 - if (has_some && !has_all) -
2929 - { -
2930 - appendPQExpBufferStr(&buf, " ("); -
2931 - -
2932 - /* options */ -
2933 - if (has_ndistinct) -
2934 - { -
2935 - appendPQExpBufferStr(&buf, "ndistinct"); -
2936 - gotone = true; -
2937 - } -
2938 - -
2939 - if (has_dependencies) -
2940 - { -
2941 - appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : ""); -
2942 - gotone = true; -
2943 - } -
2944 - -
2945 - if (has_mcv) -
2946 - { -
2947 - appendPQExpBuffer(&buf, "%smcv", gotone ? ", " : ""); -
2948 - } -
2949 - -
2950 - appendPQExpBufferChar(&buf, ')'); -
2951 - } -
2952 - -
2953 - appendPQExpBuffer(&buf, " ON %s FROM %s", -
2954 - PQgetvalue(result, i, 4), -
2955 - PQgetvalue(result, i, 1)); -
2956 - -
2957 - /* Show the stats target if it's not default */ -
2958 - if (!PQgetisnull(result, i, 8) && -
2959 - strcmp(PQgetvalue(result, i, 8), "-1") != 0) -
2960 - appendPQExpBuffer(&buf, "; STATISTICS %s", -
2961 - PQgetvalue(result, i, 8)); -
2962 - -
2963 - printTableAddFooter(&cont, buf.data); -
2964 - } -
2965 - } -
2966 - PQclear(result); -
2967 - } -
2968 - else if (pset.sversion >= 100000) -
2969 - { -
2970 - printfPQExpBuffer(&buf, -
2971 - "SELECT oid, " -
2972 - "stxrelid::pg_catalog.regclass, " -
2973 - "stxnamespace::pg_catalog.regnamespace AS nsp, " -
2974 - "stxname,\n" -
2975 - " (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(attname),', ')\n" -
2976 - " FROM pg_catalog.unnest(stxkeys) s(attnum)\n" -
2977 - " JOIN pg_catalog.pg_attribute a ON (stxrelid = a.attrelid AND\n" -
2978 - " a.attnum = s.attnum AND NOT attisdropped)) AS columns,\n" -
2979 - " " CppAsString2(STATS_EXT_NDISTINCT) " = any(stxkind) AS ndist_enabled,\n" -
2980 - " " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(stxkind) AS deps_enabled,\n" -
2981 - " " CppAsString2(STATS_EXT_MCV) " = any(stxkind) AS mcv_enabled,\n"); -
2982 - -
2983 - if (pset.sversion >= 130000) -
2984 - appendPQExpBufferStr(&buf, " stxstattarget\n"); -
2985 - else -
2986 - appendPQExpBufferStr(&buf, " -1 AS stxstattarget\n"); -
2987 - appendPQExpBuffer(&buf, "FROM pg_catalog.pg_statistic_ext\n" -
2988 - "WHERE stxrelid = '%s'\n" -
2989 - "ORDER BY 1;", -
2990 - oid); -
2991 - -
2992 - result = PSQLexec(buf.data); -
2993 - if (!result) -
2994 - goto error_return; -
2995 - else -
2996 - tuples = PQntuples(result); -
2997 - -
2998 - if (tuples > 0) -
2999 - { -
3000 - printTableAddFooter(&cont, _("Statistics objects:")); -
3001 - -
3002 - for (i = 0; i < tuples; i++) -
3003 - { -
3004 - bool gotone = false; -
3005 - -
3006 - printfPQExpBuffer(&buf, " "); -
3007 - -
3008 - /* statistics object name (qualified with namespace) */ -
3009 - appendPQExpBuffer(&buf, "\"%s.%s\" (", -
3010 - PQgetvalue(result, i, 2), -
3011 - PQgetvalue(result, i, 3)); -
3012 - -
3013 - /* options */ -
3014 - if (strcmp(PQgetvalue(result, i, 5), "t") == 0) -
3015 - { -
3016 - appendPQExpBufferStr(&buf, "ndistinct"); -
3017 - gotone = true; -
3018 - } -
3019 - -
3020 - if (strcmp(PQgetvalue(result, i, 6), "t") == 0) -
3021 - { -
3022 - appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : ""); -
3023 - gotone = true; -
3024 - } -
3025 - -
3026 - if (strcmp(PQgetvalue(result, i, 7), "t") == 0) -
3027 - { -
3028 - appendPQExpBuffer(&buf, "%smcv", gotone ? ", " : ""); -
3029 - } -
3030 - -
3031 - appendPQExpBuffer(&buf, ") ON %s FROM %s", -
3032 - PQgetvalue(result, i, 4), -
3033 - PQgetvalue(result, i, 1)); -
3034 - -
3035 - /* Show the stats target if it's not default */ -
3036 - if (strcmp(PQgetvalue(result, i, 8), "-1") != 0) -
3037 - appendPQExpBuffer(&buf, "; STATISTICS %s", -
3038 - PQgetvalue(result, i, 8)); -
3039 - -
3040 - printTableAddFooter(&cont, buf.data); -
3041 - } -
3042 - } -
3043 - PQclear(result); -
3044 - } -
3045 - -
3046 - /* print rules */ -
3047 - if (tableinfo.hasrules && tableinfo.relkind != RELKIND_MATVIEW) -
3048 - { -
3049 - printfPQExpBuffer(&buf, -
3050 - "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), " -
3051 - "ev_enabled\n" -
3052 - "FROM pg_catalog.pg_rewrite r\n" -
3053 - "WHERE r.ev_class = '%s' ORDER BY 1;", -
3054 - oid); -
3055 - result = PSQLexec(buf.data); -
3056 - if (!result) -
3057 - goto error_return; -
3058 - else -
3059 - tuples = PQntuples(result); -
3060 - -
3061 - if (tuples > 0) -
3062 - { -
3063 - bool have_heading; -
3064 - int category; -
3065 - -
3066 - for (category = 0; category < 4; category++) -
3067 - { -
3068 - have_heading = false; -
3069 - -
3070 - for (i = 0; i < tuples; i++) -
3071 - { -
3072 - const char *ruledef; -
3073 - bool list_rule = false; -
3074 - -
3075 - switch (category) -
3076 - { -
3077 - case 0: -
3078 - if (*PQgetvalue(result, i, 2) == 'O') -
3079 - list_rule = true; -
3080 - break; -
3081 - case 1: -
3082 - if (*PQgetvalue(result, i, 2) == 'D') -
3083 - list_rule = true; -
3084 - break; -
3085 - case 2: -
3086 - if (*PQgetvalue(result, i, 2) == 'A') -
3087 - list_rule = true; -
3088 - break; -
3089 - case 3: -
3090 - if (*PQgetvalue(result, i, 2) == 'R') -
3091 - list_rule = true; -
3092 - break; -
3093 - } -
3094 - if (!list_rule) -
3095 - continue; -
3096 - -
3097 - if (!have_heading) -
3098 - { -
3099 - switch (category) -
3100 - { -
3101 - case 0: -
3102 - printfPQExpBuffer(&buf, _("Rules:")); -
3103 - break; -
3104 - case 1: -
3105 - printfPQExpBuffer(&buf, _("Disabled rules:")); -
3106 - break; -
3107 - case 2: -
3108 - printfPQExpBuffer(&buf, _("Rules firing always:")); -
3109 - break; -
3110 - case 3: -
3111 - printfPQExpBuffer(&buf, _("Rules firing on replica only:")); -
3112 - break; -
3113 - } -
3114 - printTableAddFooter(&cont, buf.data); -
3115 - have_heading = true; -
3116 - } -
3117 - -
3118 - /* Everything after "CREATE RULE" is echoed verbatim */ -
3119 - ruledef = PQgetvalue(result, i, 1); -
3120 - ruledef += 12; -
3121 - printfPQExpBuffer(&buf, " %s", ruledef); -
3122 - printTableAddFooter(&cont, buf.data); -
3123 - } -
3124 - } -
3125 - } -
3126 - PQclear(result); -
3127 - } -
3128 - -
3129 - /* print any publications */ -
3130 - if (pset.sversion >= 100000) -
3131 - { -
3132 - if (pset.sversion >= 150000) -
3133 - { -
3134 - printfPQExpBuffer(&buf, -
3135 - "SELECT pubname\n" -
3136 - " , NULL\n" -
3137 - " , NULL\n" -
3138 - "FROM pg_catalog.pg_publication p\n" -
3139 - " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n" -
3140 - " JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n" -
3141 - "WHERE pc.oid ='%s' and pg_catalog.pg_relation_is_publishable('%s')\n" -
3142 - "UNION\n" -
3143 - "SELECT pubname\n" -
3144 - " , pg_get_expr(pr.prqual, c.oid)\n" -
3145 - " , (CASE WHEN pr.prattrs IS NOT NULL THEN\n" -
3146 - " (SELECT string_agg(attname, ', ')\n" -
3147 - " FROM pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n" -
3148 - " pg_catalog.pg_attribute\n" -
3149 - " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n" -
3150 - " ELSE NULL END) " -
3151 - "FROM pg_catalog.pg_publication p\n" -
3152 - " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n" -
3153 - " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n" -
3154 - "WHERE pr.prrelid = '%s'\n" -
3155 - "UNION\n" -
3156 - "SELECT pubname\n" -
3157 - " , NULL\n" -
3158 - " , NULL\n" -
3159 - "FROM pg_catalog.pg_publication p\n" -
3160 - "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n" -
3161 - "ORDER BY 1;", -
3162 - oid, oid, oid, oid); -
3163 - } -
3164 - else -
3165 - { -
3166 - printfPQExpBuffer(&buf, -
3167 - "SELECT pubname\n" -
3168 - " , NULL\n" -
3169 - " , NULL\n" -
3170 - "FROM pg_catalog.pg_publication p\n" -
3171 - "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n" -
3172 - "WHERE pr.prrelid = '%s'\n" -
3173 - "UNION ALL\n" -
3174 - "SELECT pubname\n" -
3175 - " , NULL\n" -
3176 - " , NULL\n" -
3177 - "FROM pg_catalog.pg_publication p\n" -
3178 - "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n" -
3179 - "ORDER BY 1;", -
3180 - oid, oid); -
3181 - } -
3182 - -
3183 - result = PSQLexec(buf.data); -
3184 - if (!result) -
3185 - goto error_return; -
3186 - else -
3187 - tuples = PQntuples(result); -
3188 - -
3189 - if (tuples > 0) -
3190 - printTableAddFooter(&cont, _("Publications:")); -
3191 - -
3192 - /* Might be an empty set - that's ok */ -
3193 - for (i = 0; i < tuples; i++) -
3194 - { -
3195 - printfPQExpBuffer(&buf, " \"%s\"", -
3196 - PQgetvalue(result, i, 0)); -
3197 - -
3198 - /* column list (if any) */ -
3199 - if (!PQgetisnull(result, i, 2)) -
3200 - appendPQExpBuffer(&buf, " (%s)", -
3201 - PQgetvalue(result, i, 2)); -
3202 - -
3203 - /* row filter (if any) */ -
3204 - if (!PQgetisnull(result, i, 1)) -
3205 - appendPQExpBuffer(&buf, " WHERE %s", -
3206 - PQgetvalue(result, i, 1)); -
3207 - -
3208 - printTableAddFooter(&cont, buf.data); -
3209 - } -
3210 - PQclear(result); -
3211 - } -
3212 - -
3213 - /* -
3214 - * If verbose, print NOT NULL constraints. -
3215 - */ -
3216 - if (verbose) -
3217 - { -
3218 - printfPQExpBuffer(&buf, -
3219 - "SELECT c.conname, a.attname, c.connoinherit,\n" -
3220 - " c.conislocal, c.coninhcount <> 0,\n" -
3221 - " c.convalidated\n" -
3222 - "FROM pg_catalog.pg_constraint c JOIN\n" -
3223 - " pg_catalog.pg_attribute a ON\n" -
3224 - " (a.attrelid = c.conrelid AND a.attnum = c.conkey[1])\n" -
3225 - "WHERE c.contype = " CppAsString2(CONSTRAINT_NOTNULL) " AND\n" -
3226 - " c.conrelid = '%s'::pg_catalog.regclass\n" -
3227 - "ORDER BY a.attnum", -
3228 - oid); -
3229 - -
3230 - result = PSQLexec(buf.data); -
3231 - if (!result) -
3232 - goto error_return; -
3233 - else -
3234 - tuples = PQntuples(result); -
3235 - -
3236 - if (tuples > 0) -
3237 - printTableAddFooter(&cont, _("Not-null constraints:")); -
3238 - -
3239 - /* Might be an empty set - that's ok */ -
3240 - for (i = 0; i < tuples; i++) -
3241 - { -
3242 - bool islocal = PQgetvalue(result, i, 3)[0] == 't'; -
3243 - bool inherited = PQgetvalue(result, i, 4)[0] == 't'; -
3244 - bool validated = PQgetvalue(result, i, 5)[0] == 't'; -
3245 - -
3246 - printfPQExpBuffer(&buf, " \"%s\" NOT NULL \"%s\"%s%s", -
3247 - PQgetvalue(result, i, 0), -
3248 - PQgetvalue(result, i, 1), -
3249 - PQgetvalue(result, i, 2)[0] == 't' ? -
3250 - " NO INHERIT" : -
3251 - islocal && inherited ? _(" (local, inherited)") : -
3252 - inherited ? _(" (inherited)") : "", -
3253 - !validated ? " NOT VALID" : ""); -
3254 - -
3255 - printTableAddFooter(&cont, buf.data); -
3256 - } -
3257 - PQclear(result); -
3258 - } -
3259 - } -
3260 - -
3261 - /* Get view_def if table is a view or materialized view */ -
3262 - if ((tableinfo.relkind == RELKIND_VIEW || -
3263 - tableinfo.relkind == RELKIND_MATVIEW) && verbose) -
3264 - { -
3265 - PGresult *result; -
3266 - -
3267 - printfPQExpBuffer(&buf, -
3268 - "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);", -
3269 - oid); -
3270 - result = PSQLexec(buf.data); -
3271 - if (!result) -
3272 - goto error_return; -
3273 - -
3274 - if (PQntuples(result) > 0) -
3275 - view_def = pg_strdup(PQgetvalue(result, 0, 0)); -
3276 - -
3277 - PQclear(result); -
3278 - } -
3279 - -
3280 - if (view_def) -
3281 - { -
3282 - PGresult *result = NULL; -
3283 - -
3284 - /* Footer information about a view */ -
3285 - printTableAddFooter(&cont, _("View definition:")); -
3286 - printTableAddFooter(&cont, view_def); -
3287 - -
3288 - /* print rules */ -
3289 - if (tableinfo.hasrules) -
3290 - { -
3291 - printfPQExpBuffer(&buf, -
3292 - "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n" -
3293 - "FROM pg_catalog.pg_rewrite r\n" -
3294 - "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1;", -
3295 - oid); -
3296 - result = PSQLexec(buf.data); -
3297 - if (!result) -
3298 - goto error_return; -
3299 - -
3300 - if (PQntuples(result) > 0) -
3301 - { -
3302 - printTableAddFooter(&cont, _("Rules:")); -
3303 - for (i = 0; i < PQntuples(result); i++) -
3304 - { -
3305 - const char *ruledef; -
3306 - -
3307 - /* Everything after "CREATE RULE" is echoed verbatim */ -
3308 - ruledef = PQgetvalue(result, i, 1); -
3309 - ruledef += 12; -
3310 - -
3311 - printfPQExpBuffer(&buf, " %s", ruledef); -
3312 - printTableAddFooter(&cont, buf.data); -
3313 - } -
3314 - } -
3315 - PQclear(result); -
3316 - } -
3317 - } -
3318 - -
3319 - /* -
3320 - * Print triggers next, if any (but only user-defined triggers). This -
3321 - * could apply to either a table or a view. -
3322 - */ -
3323 - if (tableinfo.hastriggers) -
3324 - { -
3325 - PGresult *result; -
3326 - int tuples; -
3327 - -
3328 - printfPQExpBuffer(&buf, -
3329 - "SELECT t.tgname, " -
3330 - "pg_catalog.pg_get_triggerdef(t.oid, true), " -
3331 - "t.tgenabled, t.tgisinternal,\n"); -
3332 - -
3333 - /* -
3334 - * Detect whether each trigger is inherited, and if so, get the name -
3335 - * of the topmost table it's inherited from. We have no easy way to -
3336 - * do that pre-v13, for lack of the tgparentid column. Even with -
3337 - * tgparentid, a straightforward search for the topmost parent would -
3338 - * require a recursive CTE, which seems unduly expensive. We cheat a -
3339 - * bit by assuming parent triggers will match by tgname; then, joining -
3340 - * with pg_partition_ancestors() allows the planner to make use of -
3341 - * pg_trigger_tgrelid_tgname_index if it wishes. We ensure we find -
3342 - * the correct topmost parent by stopping at the first-in-partition- -
3343 - * ancestry-order trigger that has tgparentid = 0. (There might be -
3344 - * unrelated, non-inherited triggers with the same name further up the -
3345 - * stack, so this is important.) -
3346 - */ -
3347 - if (pset.sversion >= 130000) -
3348 - appendPQExpBufferStr(&buf, -
3349 - " CASE WHEN t.tgparentid != 0 THEN\n" -
3350 - " (SELECT u.tgrelid::pg_catalog.regclass\n" -
3351 - " FROM pg_catalog.pg_trigger AS u,\n" -
3352 - " pg_catalog.pg_partition_ancestors(t.tgrelid) WITH ORDINALITY AS a(relid, depth)\n" -
3353 - " WHERE u.tgname = t.tgname AND u.tgrelid = a.relid\n" -
3354 - " AND u.tgparentid = 0\n" -
3355 - " ORDER BY a.depth LIMIT 1)\n" -
3356 - " END AS parent\n"); -
3357 - else -
3358 - appendPQExpBufferStr(&buf, " NULL AS parent\n"); -
3359 - -
3360 - appendPQExpBuffer(&buf, -
3361 - "FROM pg_catalog.pg_trigger t\n" -
3362 - "WHERE t.tgrelid = '%s' AND ", -
3363 - oid); -
3364 - -
3365 - /* -
3366 - * tgisinternal is set true for inherited triggers of partitions in -
3367 - * servers between v11 and v14, though these must still be shown to -
3368 - * the user. So we use another property that is true for such -
3369 - * inherited triggers to avoid them being hidden, which is their -
3370 - * dependence on another trigger. -
3371 - */ -
3372 - if (pset.sversion >= 110000 && pset.sversion < 150000) -
3373 - appendPQExpBufferStr(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D') \n" -
3374 - " OR EXISTS (SELECT 1 FROM pg_catalog.pg_depend WHERE objid = t.oid \n" -
3375 - " AND refclassid = 'pg_catalog.pg_trigger'::pg_catalog.regclass))"); -
3376 - else -
3377 - /* display/warn about disabled internal triggers */ -
3378 - appendPQExpBufferStr(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D'))"); -
3379 - appendPQExpBufferStr(&buf, "\nORDER BY 1;"); -
3380 - -
3381 - result = PSQLexec(buf.data); -
3382 - if (!result) -
3383 - goto error_return; -
3384 - else -
3385 - tuples = PQntuples(result); -
3386 - -
3387 - if (tuples > 0) -
3388 - { -
3389 - bool have_heading; -
3390 - int category; -
3391 - -
3392 - /* -
3393 - * split the output into 4 different categories. Enabled triggers, -
3394 - * disabled triggers and the two special ALWAYS and REPLICA -
3395 - * configurations. -
3396 - */ -
3397 - for (category = 0; category <= 4; category++) -
3398 - { -
3399 - have_heading = false; -
3400 - for (i = 0; i < tuples; i++) -
3401 - { -
3402 - bool list_trigger; -
3403 - const char *tgdef; -
3404 - const char *usingpos; -
3405 - const char *tgenabled; -
3406 - const char *tgisinternal; -
3407 - -
3408 - /* -
3409 - * Check if this trigger falls into the current category -
3410 - */ -
3411 - tgenabled = PQgetvalue(result, i, 2); -
3412 - tgisinternal = PQgetvalue(result, i, 3); -
3413 - list_trigger = false; -
3414 - switch (category) -
3415 - { -
3416 - case 0: -
3417 - if (*tgenabled == 'O' || *tgenabled == 't') -
3418 - list_trigger = true; -
3419 - break; -
3420 - case 1: -
3421 - if ((*tgenabled == 'D' || *tgenabled == 'f') && -
3422 - *tgisinternal == 'f') -
3423 - list_trigger = true; -
3424 - break; -
3425 - case 2: -
3426 - if ((*tgenabled == 'D' || *tgenabled == 'f') && -
3427 - *tgisinternal == 't') -
3428 - list_trigger = true; -
3429 - break; -
3430 - case 3: -
3431 - if (*tgenabled == 'A') -
3432 - list_trigger = true; -
3433 - break; -
3434 - case 4: -
3435 - if (*tgenabled == 'R') -
3436 - list_trigger = true; -
3437 - break; -
3438 - } -
3439 - if (list_trigger == false) -
3440 - continue; -
3441 - -
3442 - /* Print the category heading once */ -
3443 - if (have_heading == false) -
3444 - { -
3445 - switch (category) -
3446 - { -
3447 - case 0: -
3448 - printfPQExpBuffer(&buf, _("Triggers:")); -
3449 - break; -
3450 - case 1: -
3451 - printfPQExpBuffer(&buf, _("Disabled user triggers:")); -
3452 - break; -
3453 - case 2: -
3454 - printfPQExpBuffer(&buf, _("Disabled internal triggers:")); -
3455 - break; -
3456 - case 3: -
3457 - printfPQExpBuffer(&buf, _("Triggers firing always:")); -
3458 - break; -
3459 - case 4: -
3460 - printfPQExpBuffer(&buf, _("Triggers firing on replica only:")); -
3461 - break; -
3462 - } -
3463 - printTableAddFooter(&cont, buf.data); -
3464 - have_heading = true; -
3465 - } -
3466 - -
3467 - /* Everything after "TRIGGER" is echoed verbatim */ -
3468 - tgdef = PQgetvalue(result, i, 1); -
3469 - usingpos = strstr(tgdef, " TRIGGER "); -
3470 - if (usingpos) -
3471 - tgdef = usingpos + 9; -
3472 - -
3473 - printfPQExpBuffer(&buf, " %s", tgdef); -
3474 - -
3475 - /* Visually distinguish inherited triggers */ -
3476 - if (!PQgetisnull(result, i, 4)) -
3477 - appendPQExpBuffer(&buf, ", ON TABLE %s", -
3478 - PQgetvalue(result, i, 4)); -
3479 - -
3480 - printTableAddFooter(&cont, buf.data); -
3481 - } -
3482 - } -
3483 - } -
3484 - PQclear(result); -
3485 - } -
3486 - -
3487 - /* -
3488 - * Finish printing the footer information about a table. -
3489 - */ -
3490 - if (tableinfo.relkind == RELKIND_RELATION || -
3491 - tableinfo.relkind == RELKIND_MATVIEW || -
3492 - tableinfo.relkind == RELKIND_FOREIGN_TABLE || -
3493 - tableinfo.relkind == RELKIND_PARTITIONED_TABLE || -
3494 - tableinfo.relkind == RELKIND_PARTITIONED_INDEX || -
3495 - tableinfo.relkind == RELKIND_TOASTVALUE) -
3496 - { -
3497 - bool is_partitioned; -
3498 - PGresult *result; -
3499 - int tuples; -
3500 - -
3501 - /* simplify some repeated tests below */ -
3502 - is_partitioned = (tableinfo.relkind == RELKIND_PARTITIONED_TABLE || -
3503 - tableinfo.relkind == RELKIND_PARTITIONED_INDEX); -
3504 - -
3505 - /* print foreign server name */ -
3506 - if (tableinfo.relkind == RELKIND_FOREIGN_TABLE) -
3507 - { -
3508 - char *ftoptions; -
3509 - -
3510 - /* Footer information about foreign table */ -
3511 - printfPQExpBuffer(&buf, -
3512 - "SELECT s.srvname,\n" -
3513 - " pg_catalog.array_to_string(ARRAY(\n" -
3514 - " SELECT pg_catalog.quote_ident(option_name)" -
3515 - " || ' ' || pg_catalog.quote_literal(option_value)\n" -
3516 - " FROM pg_catalog.pg_options_to_table(ftoptions)), ', ')\n" -
3517 - "FROM pg_catalog.pg_foreign_table f,\n" -
3518 - " pg_catalog.pg_foreign_server s\n" -
3519 - "WHERE f.ftrelid = '%s' AND s.oid = f.ftserver;", -
3520 - oid); -
3521 - result = PSQLexec(buf.data); -
3522 - if (!result) -
3523 - goto error_return; -
3524 - else if (PQntuples(result) != 1) -
3525 - { -
3526 - PQclear(result); -
3527 - goto error_return; -
3528 - } -
3529 - -
3530 - /* Print server name */ -
3531 - printfPQExpBuffer(&buf, _("Server: %s"), -
3532 - PQgetvalue(result, 0, 0)); -
3533 - printTableAddFooter(&cont, buf.data); -
3534 - -
3535 - /* Print per-table FDW options, if any */ -
3536 - ftoptions = PQgetvalue(result, 0, 1); -
3537 - if (ftoptions && ftoptions[0] != '\0') -
3538 - { -
3539 - printfPQExpBuffer(&buf, _("FDW options: (%s)"), ftoptions); -
3540 - printTableAddFooter(&cont, buf.data); -
3541 - } -
3542 - PQclear(result); -
3543 - } -
3544 - -
3545 - /* print tables inherited from (exclude partitioned parents) */ -
3546 - printfPQExpBuffer(&buf, -
3547 - "SELECT c.oid::pg_catalog.regclass\n" -
3548 - "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n" -
3549 - "WHERE c.oid = i.inhparent AND i.inhrelid = '%s'\n" -
3550 - " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_TABLE) -
3551 - " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_INDEX) -
3552 - "\nORDER BY inhseqno;", -
3553 - oid); -
3554 - -
3555 - result = PSQLexec(buf.data); -
3556 - if (!result) -
3557 - goto error_return; -
3558 - else -
3559 - { -
3560 - const char *s = _("Inherits"); -
3561 - int sw = pg_wcswidth(s, strlen(s), pset.encoding); -
3562 - -
3563 - tuples = PQntuples(result); -
3564 - -
3565 - for (i = 0; i < tuples; i++) -
3566 - { -
3567 - if (i == 0) -
3568 - printfPQExpBuffer(&buf, "%s: %s", -
3569 - s, PQgetvalue(result, i, 0)); -
3570 - else -
3571 - printfPQExpBuffer(&buf, "%*s %s", -
3572 - sw, "", PQgetvalue(result, i, 0)); -
3573 - if (i < tuples - 1) -
3574 - appendPQExpBufferChar(&buf, ','); -
3575 - -
3576 - printTableAddFooter(&cont, buf.data); -
3577 - } -
3578 - -
3579 - PQclear(result); -
3580 - } -
3581 - -
3582 - /* print child tables (with additional info if partitions) */ -
3583 - if (pset.sversion >= 140000) -
3584 - printfPQExpBuffer(&buf, -
3585 - "SELECT c.oid::pg_catalog.regclass, c.relkind," -
3586 - " inhdetachpending," -
3587 - " pg_catalog.pg_get_expr(c.relpartbound, c.oid)\n" -
3588 - "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n" -
3589 - "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n" -
3590 - "ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT'," -
3591 - " c.oid::pg_catalog.regclass::pg_catalog.text;", -
3592 - oid); -
3593 - else if (pset.sversion >= 100000) -
3594 - printfPQExpBuffer(&buf, -
3595 - "SELECT c.oid::pg_catalog.regclass, c.relkind," -
3596 - " false AS inhdetachpending," -
3597 - " pg_catalog.pg_get_expr(c.relpartbound, c.oid)\n" -
3598 - "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n" -
3599 - "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n" -
3600 - "ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT'," -
3601 - " c.oid::pg_catalog.regclass::pg_catalog.text;", -
3602 - oid); -
3603 - else -
3604 - printfPQExpBuffer(&buf, -
3605 - "SELECT c.oid::pg_catalog.regclass, c.relkind," -
3606 - " false AS inhdetachpending, NULL\n" -
3607 - "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n" -
3608 - "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n" -
3609 - "ORDER BY c.oid::pg_catalog.regclass::pg_catalog.text;", -
3610 - oid); -
3611 - -
3612 - result = PSQLexec(buf.data); -
3613 - if (!result) -
3614 - goto error_return; -
3615 - tuples = PQntuples(result); -
3616 - -
3617 - /* -
3618 - * For a partitioned table with no partitions, always print the number -
3619 - * of partitions as zero, even when verbose output is expected. -
3620 - * Otherwise, we will not print "Partitions" section for a partitioned -
3621 - * table without any partitions. -
3622 - */ -
3623 - if (is_partitioned && tuples == 0) -
3624 - { -
3625 - printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples); -
3626 - printTableAddFooter(&cont, buf.data); -
3627 - } -
3628 - else if (!verbose) -
3629 - { -
3630 - /* print the number of child tables, if any */ -
3631 - if (tuples > 0) -
3632 - { -
3633 - if (is_partitioned) -
3634 - printfPQExpBuffer(&buf, _("Number of partitions: %d (Use \\d+ to list them.)"), tuples); -
3635 - else -
3636 - printfPQExpBuffer(&buf, _("Number of child tables: %d (Use \\d+ to list them.)"), tuples); -
3637 - printTableAddFooter(&cont, buf.data); -
3638 - } -
3639 - } -
3640 - else -
3641 - { -
3642 - /* display the list of child tables */ -
3643 - const char *ct = is_partitioned ? _("Partitions") : _("Child tables"); -
3644 - int ctw = pg_wcswidth(ct, strlen(ct), pset.encoding); -
3645 - -
3646 - for (i = 0; i < tuples; i++) -
3647 - { -
3648 - char child_relkind = *PQgetvalue(result, i, 1); -
3649 - -
3650 - if (i == 0) -
3651 - printfPQExpBuffer(&buf, "%s: %s", -
3652 - ct, PQgetvalue(result, i, 0)); -
3653 - else -
3654 - printfPQExpBuffer(&buf, "%*s %s", -
3655 - ctw, "", PQgetvalue(result, i, 0)); -
3656 - if (!PQgetisnull(result, i, 3)) -
3657 - appendPQExpBuffer(&buf, " %s", PQgetvalue(result, i, 3)); -
3658 - if (child_relkind == RELKIND_PARTITIONED_TABLE || -
3659 - child_relkind == RELKIND_PARTITIONED_INDEX) -
3660 - appendPQExpBufferStr(&buf, ", PARTITIONED"); -
3661 - else if (child_relkind == RELKIND_FOREIGN_TABLE) -
3662 - appendPQExpBufferStr(&buf, ", FOREIGN"); -
3663 - if (strcmp(PQgetvalue(result, i, 2), "t") == 0) -
3664 - appendPQExpBufferStr(&buf, " (DETACH PENDING)"); -
3665 - if (i < tuples - 1) -
3666 - appendPQExpBufferChar(&buf, ','); -
3667 - -
3668 - printTableAddFooter(&cont, buf.data); -
3669 - } -
3670 - } -
3671 - PQclear(result); -
3672 - -
3673 - /* Table type */ -
3674 - if (tableinfo.reloftype) -
3675 - { -
3676 - printfPQExpBuffer(&buf, _("Typed table of type: %s"), tableinfo.reloftype); -
3677 - printTableAddFooter(&cont, buf.data); -
3678 - } -
3679 - -
3680 - if (verbose && -
3681 - (tableinfo.relkind == RELKIND_RELATION || -
3682 - tableinfo.relkind == RELKIND_MATVIEW) && -
3683 - -
3684 - /* -
3685 - * No need to display default values; we already display a REPLICA -
3686 - * IDENTITY marker on indexes. -
3687 - */ -
3688 - tableinfo.relreplident != REPLICA_IDENTITY_INDEX && -
3689 - ((strcmp(schemaname, "pg_catalog") != 0 && -
3690 - tableinfo.relreplident != REPLICA_IDENTITY_DEFAULT) || -
3691 - (strcmp(schemaname, "pg_catalog") == 0 && -
3692 - tableinfo.relreplident != REPLICA_IDENTITY_NOTHING))) -
3693 - { -
3694 - const char *s = _("Replica Identity"); -
3695 - -
3696 - printfPQExpBuffer(&buf, "%s: %s", -
3697 - s, -
3698 - tableinfo.relreplident == REPLICA_IDENTITY_FULL ? "FULL" : -
3699 - tableinfo.relreplident == REPLICA_IDENTITY_DEFAULT ? "NOTHING" : -
3700 - "???"); -
3701 - -
3702 - printTableAddFooter(&cont, buf.data); -
3703 - } -
3704 - -
3705 - /* OIDs, if verbose and not a materialized view */ -
3706 - if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids) -
3707 - printTableAddFooter(&cont, _("Has OIDs: yes")); -
3708 - -
3709 - /* Tablespace info */ -
3710 - add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace, -
3711 - true); -
3712 - -
3713 - /* Access method info */ -
3714 - if (verbose && tableinfo.relam != NULL && !pset.hide_tableam) -
3715 - { -
3716 - printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam); -
3717 - printTableAddFooter(&cont, buf.data); -
3718 - } -
3719 - } -
3720 - -
3721 - /* reloptions, if verbose */ -
3722 - if (verbose && -
3723 - tableinfo.reloptions && tableinfo.reloptions[0] != '\0') -
3724 - { -
3725 - const char *t = _("Options"); -
3726 - -
3727 - printfPQExpBuffer(&buf, "%s: %s", t, tableinfo.reloptions); -
3728 - printTableAddFooter(&cont, buf.data); -
3729 - } -
3730 - -
3731 - printTable(&cont, pset.queryFout, false, pset.logfile); -
3732 - -
3733 - retval = true; -
3734 - -
3735 - error_return: -
3736 - -
3737 - /* clean up */ -
3738 - if (printTableInitialized) -
3739 - printTableCleanup(&cont); -
3740 - termPQExpBuffer(&buf); -
3741 - termPQExpBuffer(&title); -
3742 - termPQExpBuffer(&tmpbuf); -
3743 - -
3744 - free(view_def); -
3745 - -
3746 - PQclear(res); -
3747 - -
3748 - return retval; -
3749 - } -
listTables() lines 4118-4366
Modified Lines Coverage: 7/10 lines (70.0%)
LineHitsSourceCommit
4118 - listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem) -
4119 - { -
4120 - bool showTables = strchr(tabtypes, 't') != NULL; -
4121 - bool showIndexes = strchr(tabtypes, 'i') != NULL; -
4122 - bool showViews = strchr(tabtypes, 'v') != NULL; -
4123 - bool showMatViews = strchr(tabtypes, 'm') != NULL; -
4124 - bool showSeq = strchr(tabtypes, 's') != NULL; -
4125 - bool showForeign = strchr(tabtypes, 'E') != NULL; -
4126 189 bool showPropGraphs = strchr(tabtypes, 'G') != NULL; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4127 - -
4128 - int ntypes; -
4129 - PQExpBufferData buf; -
4130 - PGresult *res; -
4131 - printQueryOpt myopt = pset.popt; -
4132 - int cols_so_far; -
4133 - bool translate_columns[] = {false, false, true, false, false, false, false, false, false}; -
4134 - -
4135 - /* Count the number of explicitly-requested relation types */ -
4136 - ntypes = showTables + showIndexes + showViews + showMatViews + -
4137 189 showSeq + showForeign + showPropGraphs; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4138 - /* If none, we default to \dtvmsEG (but see also command.c) */ 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4139 - if (ntypes == 0) -
4140 0 showTables = showViews = showMatViews = showSeq = showForeign = showPropGraphs = true; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4141 - -
4142 - initPQExpBuffer(&buf); -
4143 - -
4144 - printfPQExpBuffer(&buf, -
4145 - "SELECT n.nspname as \"%s\",\n" -
4146 - " c.relname as \"%s\",\n" -
4147 - " CASE c.relkind" -
4148 - " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'" -
4149 - " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'" -
4150 - " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'" -
4151 - " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'" -
4152 - " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'" -
4153 - " WHEN " CppAsString2(RELKIND_TOASTVALUE) " THEN '%s'" -
4154 - " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'" -
4155 - " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'" -
4156 - " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'" -
4157 - " WHEN " CppAsString2(RELKIND_PROPGRAPH) " THEN '%s'" 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4158 - " END as \"%s\",\n" -
4159 - " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"", -
4160 - gettext_noop("Schema"), -
4161 - gettext_noop("Name"), -
4162 - gettext_noop("table"), -
4163 - gettext_noop("view"), -
4164 - gettext_noop("materialized view"), -
4165 - gettext_noop("index"), -
4166 - gettext_noop("sequence"), -
4167 - gettext_noop("TOAST table"), -
4168 - gettext_noop("foreign table"), -
4169 - gettext_noop("partitioned table"), -
4170 - gettext_noop("partitioned index"), -
4171 - gettext_noop("property graph"), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4172 - gettext_noop("Type"), -
4173 - gettext_noop("Owner")); -
4174 - cols_so_far = 4; -
4175 - -
4176 - if (showIndexes) -
4177 - { -
4178 - appendPQExpBuffer(&buf, -
4179 - ",\n c2.relname as \"%s\"", -
4180 - gettext_noop("Table")); -
4181 - cols_so_far++; -
4182 - } -
4183 - -
4184 - if (verbose) -
4185 - { -
4186 - /* -
4187 - * Show whether a relation is permanent, temporary, or unlogged. -
4188 - */ -
4189 - appendPQExpBuffer(&buf, -
4190 - ",\n CASE c.relpersistence " -
4191 - "WHEN " CppAsString2(RELPERSISTENCE_PERMANENT) " THEN '%s' " -
4192 - "WHEN " CppAsString2(RELPERSISTENCE_TEMP) " THEN '%s' " -
4193 - "WHEN " CppAsString2(RELPERSISTENCE_UNLOGGED) " THEN '%s' " -
4194 - "END as \"%s\"", -
4195 - gettext_noop("permanent"), -
4196 - gettext_noop("temporary"), -
4197 - gettext_noop("unlogged"), -
4198 - gettext_noop("Persistence")); -
4199 - translate_columns[cols_so_far] = true; -
4200 - -
4201 - /* -
4202 - * We don't bother to count cols_so_far below here, as there's no need -
4203 - * to; this might change with future additions to the output columns. -
4204 - */ -
4205 - -
4206 - /* -
4207 - * Access methods exist for tables, materialized views and indexes. -
4208 - * This has been introduced in PostgreSQL 12 for tables. -
4209 - */ -
4210 - if (pset.sversion >= 120000 && !pset.hide_tableam && -
4211 - (showTables || showMatViews || showIndexes)) -
4212 - appendPQExpBuffer(&buf, -
4213 - ",\n am.amname as \"%s\"", -
4214 - gettext_noop("Access method")); -
4215 - -
4216 - appendPQExpBuffer(&buf, -
4217 - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" -
4218 - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", -
4219 - gettext_noop("Size"), -
4220 - gettext_noop("Description")); -
4221 - } -
4222 - -
4223 - appendPQExpBufferStr(&buf, -
4224 - "\nFROM pg_catalog.pg_class c" -
4225 - "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"); -
4226 - -
4227 - if (pset.sversion >= 120000 && !pset.hide_tableam && -
4228 - (showTables || showMatViews || showIndexes)) -
4229 - appendPQExpBufferStr(&buf, -
4230 - "\n LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam"); -
4231 - -
4232 - if (showIndexes) -
4233 - appendPQExpBufferStr(&buf, -
4234 - "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid" -
4235 - "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid"); -
4236 - -
4237 - appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN ("); -
4238 - if (showTables) -
4239 - { -
4240 - appendPQExpBufferStr(&buf, CppAsString2(RELKIND_RELATION) "," -
4241 - CppAsString2(RELKIND_PARTITIONED_TABLE) ","); -
4242 - /* with 'S' or a pattern, allow 't' to match TOAST tables too */ -
4243 - if (showSystem || pattern) -
4244 - appendPQExpBufferStr(&buf, CppAsString2(RELKIND_TOASTVALUE) ","); -
4245 - } -
4246 - if (showViews) -
4247 - appendPQExpBufferStr(&buf, CppAsString2(RELKIND_VIEW) ","); -
4248 - if (showMatViews) -
4249 - appendPQExpBufferStr(&buf, CppAsString2(RELKIND_MATVIEW) ","); -
4250 - if (showIndexes) -
4251 - appendPQExpBufferStr(&buf, CppAsString2(RELKIND_INDEX) "," -
4252 - CppAsString2(RELKIND_PARTITIONED_INDEX) ","); -
4253 - if (showSeq) -
4254 - appendPQExpBufferStr(&buf, CppAsString2(RELKIND_SEQUENCE) ","); -
4255 - if (showSystem || pattern) -
4256 - appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL */ -
4257 - if (showForeign) -
4258 - appendPQExpBufferStr(&buf, CppAsString2(RELKIND_FOREIGN_TABLE) ","); -
4259 189 if (showPropGraphs) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4260 27 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PROPGRAPH) ","); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4261 - -
4262 - appendPQExpBufferStr(&buf, "''"); /* dummy */ -
4263 - appendPQExpBufferStr(&buf, ")\n"); -
4264 - -
4265 - if (!showSystem && !pattern) -
4266 - appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" -
4267 - " AND n.nspname !~ '^pg_toast'\n" -
4268 - " AND n.nspname <> 'information_schema'\n"); -
4269 - -
4270 - if (!validateSQLNamePattern(&buf, pattern, true, false, -
4271 - "n.nspname", "c.relname", NULL, -
4272 - "pg_catalog.pg_table_is_visible(c.oid)", -
4273 - NULL, 3)) -
4274 - { -
4275 - termPQExpBuffer(&buf); -
4276 - return false; -
4277 - } -
4278 - -
4279 - appendPQExpBufferStr(&buf, "ORDER BY 1,2;"); -
4280 - -
4281 - res = PSQLexec(buf.data); -
4282 - termPQExpBuffer(&buf); -
4283 - if (!res) -
4284 - return false; -
4285 - -
4286 - /* -
4287 - * Most functions in this file are content to print an empty table when -
4288 - * there are no matching objects. We intentionally deviate from that -
4289 - * here, but only in !quiet mode, for historical reasons. -
4290 - */ -
4291 - if (PQntuples(res) == 0 && !pset.quiet) -
4292 - { -
4293 - if (pattern) -
4294 - { -
4295 - if (ntypes != 1) -
4296 - pg_log_error("Did not find any relations named \"%s\".", -
4297 - pattern); -
4298 - else if (showTables) -
4299 - pg_log_error("Did not find any tables named \"%s\".", -
4300 - pattern); -
4301 - else if (showIndexes) -
4302 - pg_log_error("Did not find any indexes named \"%s\".", -
4303 - pattern); -
4304 - else if (showViews) -
4305 - pg_log_error("Did not find any views named \"%s\".", -
4306 - pattern); -
4307 - else if (showMatViews) -
4308 - pg_log_error("Did not find any materialized views named \"%s\".", -
4309 - pattern); -
4310 - else if (showSeq) -
4311 - pg_log_error("Did not find any sequences named \"%s\".", -
4312 - pattern); -
4313 - else if (showForeign) -
4314 - pg_log_error("Did not find any foreign tables named \"%s\".", -
4315 - pattern); -
4316 3 else if (showPropGraphs) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4317 3 pg_log_error("Did not find any property graphs named \"%s\".", 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4318 - pattern); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4319 - else /* should not get here */ -
4320 - pg_log_error_internal("Did not find any ??? named \"%s\".", -
4321 - pattern); -
4322 - } -
4323 - else -
4324 - { -
4325 - if (ntypes != 1) -
4326 - pg_log_error("Did not find any relations."); -
4327 - else if (showTables) -
4328 - pg_log_error("Did not find any tables."); -
4329 - else if (showIndexes) -
4330 - pg_log_error("Did not find any indexes."); -
4331 - else if (showViews) -
4332 - pg_log_error("Did not find any views."); -
4333 - else if (showMatViews) -
4334 - pg_log_error("Did not find any materialized views."); -
4335 - else if (showSeq) -
4336 - pg_log_error("Did not find any sequences."); -
4337 - else if (showForeign) -
4338 - pg_log_error("Did not find any foreign tables."); -
4339 0 else if (showPropGraphs) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4340 0 pg_log_error("Did not find any property graphs."); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4341 - else /* should not get here */ -
4342 - pg_log_error_internal("Did not find any ??? relations."); -
4343 - } -
4344 - } -
4345 - else -
4346 - { -
4347 - myopt.title = -
4348 - (ntypes != 1) ? _("List of relations") : -
4349 - (showTables) ? _("List of tables") : -
4350 - (showIndexes) ? _("List of indexes") : -
4351 - (showViews) ? _("List of views") : -
4352 - (showMatViews) ? _("List of materialized views") : -
4353 - (showSeq) ? _("List of sequences") : -
4354 - (showForeign) ? _("List of foreign tables") : -
4355 15 (showPropGraphs) ? _("List of property graphs") : 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
4356 - "List of ???"; /* should not get here */ -
4357 - myopt.translate_header = true; -
4358 - myopt.translate_columns = translate_columns; -
4359 - myopt.n_translate_columns = lengthof(translate_columns); -
4360 - -
4361 - printQuery(res, &myopt, pset.queryFout, false, pset.logfile); -
4362 - } -
4363 - -
4364 - PQclear(res); -
4365 - return true; -
4366 - } -