|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +module ArJdbc |
| 4 | + module PostgreSQL |
| 5 | + module SchemaStatements |
| 6 | + ForeignKeyDefinition = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition |
| 7 | + Utils = ActiveRecord::ConnectionAdapters::PostgreSQL::Utils |
| 8 | + |
| 9 | + def foreign_keys(table_name) |
| 10 | + scope = quoted_scope(table_name) |
| 11 | + fk_info = internal_exec_query(<<~SQL, "SCHEMA", allow_retry: true, materialize_transactions: false) |
| 12 | + SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid, c.condeferrable AS deferrable, c.condeferred AS deferred, c.conkey, c.confkey, c.conrelid, c.confrelid |
| 13 | + FROM pg_constraint c |
| 14 | + JOIN pg_class t1 ON c.conrelid = t1.oid |
| 15 | + JOIN pg_class t2 ON c.confrelid = t2.oid |
| 16 | + JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid |
| 17 | + JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid |
| 18 | + JOIN pg_namespace t3 ON c.connamespace = t3.oid |
| 19 | + WHERE c.contype = 'f' |
| 20 | + AND t1.relname = #{scope[:name]} |
| 21 | + AND t3.nspname = #{scope[:schema]} |
| 22 | + ORDER BY c.conname |
| 23 | + SQL |
| 24 | + |
| 25 | + fk_info.map do |row| |
| 26 | + to_table = Utils.unquote_identifier(row["to_table"]) |
| 27 | + # conkey = row["conkey"].scan(/\d+/).map(&:to_i) |
| 28 | + # confkey = row["confkey"].scan(/\d+/).map(&:to_i) |
| 29 | + conkey = row["conkey"] |
| 30 | + confkey = row["confkey"] |
| 31 | + |
| 32 | + if conkey.size > 1 |
| 33 | + column = column_names_from_column_numbers(row["conrelid"], conkey) |
| 34 | + primary_key = column_names_from_column_numbers(row["confrelid"], confkey) |
| 35 | + else |
| 36 | + column = Utils.unquote_identifier(row["column"]) |
| 37 | + primary_key = row["primary_key"] |
| 38 | + end |
| 39 | + |
| 40 | + options = { |
| 41 | + column: column, |
| 42 | + name: row["name"], |
| 43 | + primary_key: primary_key |
| 44 | + } |
| 45 | + |
| 46 | + options[:on_delete] = extract_foreign_key_action(row["on_delete"]) |
| 47 | + options[:on_update] = extract_foreign_key_action(row["on_update"]) |
| 48 | + options[:deferrable] = extract_constraint_deferrable(row["deferrable"], row["deferred"]) |
| 49 | + |
| 50 | + options[:validate] = row["valid"] |
| 51 | + |
| 52 | + ForeignKeyDefinition.new(table_name, to_table, options) |
| 53 | + end |
| 54 | + end |
| 55 | + end |
| 56 | + end |
| 57 | +end |
0 commit comments