@@ -32,6 +32,115 @@ def primary_key(table_name)
3232          end 
3333        end 
3434
35+         def  primary_keys ( table_name ) 
36+           return  super  unless  database_version  >= 24_02_02 
37+ 
38+           query_values ( <<~SQL ,  "SCHEMA" ) 
39+             SELECT a.attname 
40+               FROM ( 
41+                      SELECT indrelid, indkey, generate_subscripts(indkey, 1) idx 
42+                        FROM pg_index 
43+                       WHERE indrelid = #{ quote ( quote_table_name ( table_name ) ) }  ::regclass 
44+                         AND indisprimary 
45+                    ) i 
46+               JOIN pg_attribute a 
47+                 ON a.attrelid = i.indrelid 
48+                AND a.attnum = i.indkey[i.idx] 
49+                AND NOT a.attishidden 
50+              ORDER BY i.idx 
51+           SQL 
52+         end 
53+ 
54+         def  column_names_from_column_numbers ( table_oid ,  column_numbers ) 
55+           return  super  unless  database_version  >= 24_02_02 
56+ 
57+           Hash [ query ( <<~SQL ,  "SCHEMA" ) ] . values_at ( *column_numbers ) . compact 
58+             SELECT a.attnum, a.attname 
59+             FROM pg_attribute a 
60+             WHERE a.attrelid = #{ table_oid }  
61+             AND a.attnum IN (#{ column_numbers . join ( ", " ) }  ) 
62+             AND NOT a.attishidden 
63+           SQL 
64+         end 
65+ 
66+         # OVERRIDE: CockroachDB does not support deferrable constraints. 
67+         #   See: https://go.crdb.dev/issue-v/31632/v23.1 
68+         def  foreign_key_options ( from_table ,  to_table ,  options ) 
69+           options  =  super 
70+           options . delete ( :deferrable )  unless  supports_deferrable_constraints? 
71+           options 
72+         end 
73+ 
74+         # OVERRIDE: Added `unique_rowid` to the last line of the second query. 
75+         #   This is a CockroachDB-specific function used for primary keys. 
76+         #   Also make sure we don't consider `NOT VISIBLE` columns. 
77+         # 
78+         # Returns a table's primary key and belonging sequence. 
79+         def  pk_and_sequence_for ( table )  # :nodoc: 
80+           # First try looking for a sequence with a dependency on the 
81+           # given table's primary key. 
82+           result  =  query ( <<~SQL ,  "SCHEMA" ) [ 0 ] 
83+             SELECT attr.attname, nsp.nspname, seq.relname 
84+             FROM pg_class      seq, 
85+                  pg_attribute  attr, 
86+                  pg_depend     dep, 
87+                  pg_constraint cons, 
88+                  pg_namespace  nsp, 
89+                  -- TODO: use the pg_catalog.pg_attribute(attishidden) column when 
90+                  --   it is added instead of joining on crdb_internal. 
91+                  --   See https://github.com/cockroachdb/cockroach/pull/126397 
92+                  crdb_internal.table_columns tc 
93+             WHERE seq.oid           = dep.objid 
94+               AND seq.relkind       = 'S' 
95+               AND attr.attrelid     = dep.refobjid 
96+               AND attr.attnum       = dep.refobjsubid 
97+               AND attr.attrelid     = cons.conrelid 
98+               AND attr.attnum       = cons.conkey[1] 
99+               AND seq.relnamespace  = nsp.oid 
100+               AND attr.attrelid     = tc.descriptor_id 
101+               AND attr.attname      = tc.column_name 
102+               AND tc.hidden         = false 
103+               AND cons.contype      = 'p' 
104+               AND dep.classid       = 'pg_class'::regclass 
105+               AND dep.refobjid      = #{ quote ( quote_table_name ( table ) ) }  ::regclass 
106+           SQL 
107+ 
108+           if  result . nil?  || result . empty? 
109+             result  =  query ( <<~SQL ,  "SCHEMA" ) [ 0 ] 
110+               SELECT attr.attname, nsp.nspname, 
111+                 CASE 
112+                   WHEN pg_get_expr(def.adbin, def.adrelid) !~* 'nextval' THEN NULL 
113+                   WHEN split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2) ~ '.' THEN 
114+                     substr(split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2), 
115+                            strpos(split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2), '.')+1) 
116+                   ELSE split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2) 
117+                 END 
118+               FROM pg_class       t 
119+               JOIN pg_attribute   attr ON (t.oid = attrelid) 
120+               JOIN pg_attrdef     def  ON (adrelid = attrelid AND adnum = attnum) 
121+               JOIN pg_constraint  cons ON (conrelid = adrelid AND adnum = conkey[1]) 
122+               JOIN pg_namespace   nsp  ON (t.relnamespace = nsp.oid) 
123+               -- TODO: use the pg_catalog.pg_attribute(attishidden) column when 
124+               --   it is added instead of joining on crdb_internal. 
125+               --   See https://github.com/cockroachdb/cockroach/pull/126397 
126+               JOIN crdb_internal.table_columns tc ON (attr.attrelid = tc.descriptor_id AND attr.attname = tc.column_name) 
127+               WHERE t.oid = #{ quote ( quote_table_name ( table ) ) }  ::regclass 
128+                 AND tc.hidden = false 
129+                 AND cons.contype = 'p' 
130+                 AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate|gen_random_uuid|unique_rowid' 
131+             SQL 
132+           end 
133+ 
134+           pk  =  result . shift 
135+           if  result . last 
136+             [ pk ,  PostgreSQL ::Name . new ( *result ) ] 
137+           else 
138+             [ pk ,  nil ] 
139+           end 
140+         rescue 
141+           nil 
142+         end 
143+ 
35144        # override 
36145        # Modified version of the postgresql foreign_keys method. 
37146        # Replaces t2.oid::regclass::text with t2.relname since this is 
0 commit comments