|
| 1 | +-- Adapted from information_schema.columns |
| 2 | + |
1 | 3 | SELECT
|
2 | 4 | c.oid :: int8 AS table_id,
|
3 |
| - table_schema AS schema, |
4 |
| - table_name AS table, |
5 |
| - (c.oid || '.' || ordinal_position) AS id, |
6 |
| - ordinal_position, |
7 |
| - column_name AS name, |
8 |
| - column_default AS default_value, |
9 |
| - data_type, |
10 |
| - udt_name AS format, |
11 |
| - col_description(c.oid, ordinal_position) AS description, |
12 |
| - is_identity :: boolean, |
13 |
| - identity_generation, |
14 |
| - is_nullable :: boolean, |
15 |
| - is_updatable :: boolean, |
| 5 | + nc.nspname AS schema, |
| 6 | + c.relname AS table, |
| 7 | + (c.oid || '.' || a.attnum) AS id, |
| 8 | + a.attnum AS ordinal_position, |
| 9 | + a.attname AS name, |
| 10 | + CASE |
| 11 | + WHEN a.atthasdef THEN pg_get_expr(ad.adbin, ad.adrelid) |
| 12 | + ELSE NULL |
| 13 | + END AS default_value, |
| 14 | + CASE |
| 15 | + WHEN t.typtype = 'd' THEN CASE |
| 16 | + WHEN bt.typelem <> 0 :: oid |
| 17 | + AND bt.typlen = -1 THEN 'ARRAY' |
| 18 | + WHEN nbt.nspname = 'pg_catalog' THEN format_type(t.typbasetype, NULL) |
| 19 | + ELSE 'USER-DEFINED' |
| 20 | + END |
| 21 | + ELSE CASE |
| 22 | + WHEN t.typelem <> 0 :: oid |
| 23 | + AND t.typlen = -1 THEN 'ARRAY' |
| 24 | + WHEN nt.nspname = 'pg_catalog' THEN format_type(a.atttypid, NULL) |
| 25 | + ELSE 'USER-DEFINED' |
| 26 | + END |
| 27 | + END AS data_type, |
| 28 | + COALESCE(bt.typname, t.typname) AS format, |
| 29 | + CASE |
| 30 | + WHEN a.attidentity IN ('a', 'd') THEN TRUE |
| 31 | + ELSE FALSE |
| 32 | + END AS is_identity, |
| 33 | + CASE |
| 34 | + a.attidentity |
| 35 | + WHEN 'a' THEN 'ALWAYS' |
| 36 | + WHEN 'd' THEN 'BY DEFAULT' |
| 37 | + ELSE NULL |
| 38 | + END AS identity_generation, |
| 39 | + CASE |
| 40 | + WHEN a.attnotnull |
| 41 | + OR t.typtype = 'd' |
| 42 | + AND t.typnotnull THEN FALSE |
| 43 | + ELSE TRUE |
| 44 | + END AS is_nullable, |
| 45 | + CASE |
| 46 | + WHEN ( |
| 47 | + c.relkind IN ('r', 'p') |
| 48 | + ) |
| 49 | + OR ( |
| 50 | + c.relkind IN ('v', 'f') |
| 51 | + ) |
| 52 | + AND pg_column_is_updatable(c.oid, a.attnum, FALSE) THEN TRUE |
| 53 | + ELSE FALSE |
| 54 | + END AS is_updatable, |
16 | 55 | array_to_json(
|
17 | 56 | array(
|
18 | 57 | SELECT
|
19 | 58 | enumlabel
|
20 | 59 | FROM
|
21 | 60 | pg_catalog.pg_enum enums
|
22 | 61 | WHERE
|
23 |
| - udt_name = pg_catalog.Format_type(enums.enumtypid :: regclass, NULL) |
| 62 | + COALESCE(bt.typname, t.typname) = format_type(enums.enumtypid :: regclass, NULL) |
24 | 63 | ORDER BY
|
25 | 64 | enums.enumsortorder
|
26 | 65 | )
|
27 | 66 | ) AS enums,
|
28 |
| - col_description(c.oid, ordinal_position) AS comment |
| 67 | + col_description(c.oid, a.attnum) AS comment |
29 | 68 | FROM
|
30 |
| - information_schema.columns |
31 |
| - JOIN pg_class c ON quote_ident(table_schema) :: regnamespace = c.relnamespace |
32 |
| - AND c.relname = table_name |
| 69 | + pg_attribute a |
| 70 | + LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid |
| 71 | + AND a.attnum = ad.adnum |
| 72 | + JOIN ( |
| 73 | + pg_class c |
| 74 | + JOIN pg_namespace nc ON c.relnamespace = nc.oid |
| 75 | + ) ON a.attrelid = c.oid |
| 76 | + JOIN ( |
| 77 | + pg_type t |
| 78 | + JOIN pg_namespace nt ON t.typnamespace = nt.oid |
| 79 | + ) ON a.atttypid = t.oid |
| 80 | + LEFT JOIN ( |
| 81 | + pg_type bt |
| 82 | + JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid |
| 83 | + ) ON t.typtype = 'd' |
| 84 | + AND t.typbasetype = bt.oid |
| 85 | +WHERE |
| 86 | + NOT pg_is_other_temp_schema(nc.oid) |
| 87 | + AND a.attnum > 0 |
| 88 | + AND NOT a.attisdropped |
| 89 | + AND (c.relkind IN ('r', 'v', 'f', 'p')) |
| 90 | + AND ( |
| 91 | + pg_has_role(c.relowner, 'USAGE') |
| 92 | + OR has_column_privilege( |
| 93 | + c.oid, |
| 94 | + a.attnum, |
| 95 | + 'SELECT, INSERT, UPDATE, REFERENCES' |
| 96 | + ) |
| 97 | + ) |
0 commit comments