columns.ts116 lines · main
1import { safeSql } from '../pg-format'
2
3export const COLUMNS_SQL = /* SQL */ safeSql`
4-- Adapted from information_schema.columns
5
6SELECT
7 c.oid :: int8 AS table_id,
8 nc.nspname AS schema,
9 c.relname AS table,
10 (c.oid || '.' || a.attnum) AS id,
11 a.attnum AS ordinal_position,
12 a.attname AS name,
13 CASE
14 WHEN a.atthasdef THEN pg_get_expr(ad.adbin, ad.adrelid)
15 ELSE NULL
16 END AS default_value,
17 CASE
18 WHEN t.typtype = 'd' THEN CASE
19 WHEN bt.typelem <> 0 :: oid
20 AND bt.typlen = -1 THEN 'ARRAY'
21 WHEN nbt.nspname = 'pg_catalog' THEN format_type(t.typbasetype, NULL)
22 ELSE 'USER-DEFINED'
23 END
24 ELSE CASE
25 WHEN t.typelem <> 0 :: oid
26 AND t.typlen = -1 THEN 'ARRAY'
27 WHEN nt.nspname = 'pg_catalog' THEN format_type(a.atttypid, NULL)
28 ELSE 'USER-DEFINED'
29 END
30 END AS data_type,
31 COALESCE(bt.typname, t.typname) AS format,
32 COALESCE(nbt.nspname, nt.nspname) AS format_schema,
33 a.attidentity IN ('a', 'd') AS is_identity,
34 CASE
35 a.attidentity
36 WHEN 'a' THEN 'ALWAYS'
37 WHEN 'd' THEN 'BY DEFAULT'
38 ELSE NULL
39 END AS identity_generation,
40 a.attgenerated IN ('s') AS is_generated,
41 NOT (
42 a.attnotnull
43 OR t.typtype = 'd' AND t.typnotnull
44 ) AS is_nullable,
45 (
46 c.relkind IN ('r', 'p')
47 OR c.relkind IN ('v', 'f') AND pg_column_is_updatable(c.oid, a.attnum, FALSE)
48 ) AS is_updatable,
49 uniques.table_id IS NOT NULL AS is_unique,
50 check_constraints.definition AS "check",
51 array_to_json(
52 array(
53 SELECT
54 enumlabel
55 FROM
56 pg_catalog.pg_enum enums
57 WHERE
58 enums.enumtypid = coalesce(bt.oid, t.oid)
59 OR enums.enumtypid = coalesce(bt.typelem, t.typelem)
60 ORDER BY
61 enums.enumsortorder
62 )
63 ) AS enums,
64 col_description(c.oid, a.attnum) AS comment
65FROM
66 pg_attribute a
67 LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid
68 AND a.attnum = ad.adnum
69 JOIN (
70 pg_class c
71 JOIN pg_namespace nc ON c.relnamespace = nc.oid
72 ) ON a.attrelid = c.oid
73 JOIN (
74 pg_type t
75 JOIN pg_namespace nt ON t.typnamespace = nt.oid
76 ) ON a.atttypid = t.oid
77 LEFT JOIN (
78 pg_type bt
79 JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid
80 ) ON t.typtype = 'd'
81 AND t.typbasetype = bt.oid
82 LEFT JOIN (
83 SELECT DISTINCT ON (table_id, ordinal_position)
84 conrelid AS table_id,
85 conkey[1] AS ordinal_position
86 FROM pg_catalog.pg_constraint
87 WHERE contype = 'u' AND cardinality(conkey) = 1
88 ) AS uniques ON uniques.table_id = c.oid AND uniques.ordinal_position = a.attnum
89 LEFT JOIN (
90 -- We only select the first column check
91 SELECT DISTINCT ON (table_id, ordinal_position)
92 conrelid AS table_id,
93 conkey[1] AS ordinal_position,
94 substring(
95 pg_get_constraintdef(pg_constraint.oid, true),
96 8,
97 length(pg_get_constraintdef(pg_constraint.oid, true)) - 8
98 ) AS "definition"
99 FROM pg_constraint
100 WHERE contype = 'c' AND cardinality(conkey) = 1
101 ORDER BY table_id, ordinal_position, oid asc
102 ) AS check_constraints ON check_constraints.table_id = c.oid AND check_constraints.ordinal_position = a.attnum
103WHERE
104 NOT pg_is_other_temp_schema(nc.oid)
105 AND a.attnum > 0
106 AND NOT a.attisdropped
107 AND (c.relkind IN ('r', 'v', 'm', 'f', 'p'))
108 AND (
109 pg_has_role(c.relowner, 'USAGE')
110 OR has_column_privilege(
111 c.oid,
112 a.attnum,
113 'SELECT, INSERT, UPDATE, REFERENCES'
114 )
115 )
116`