Merge pull request #25307 from kamipo/extract_foreign_key_action_from_information_schema
Extract foreign key action from `information_schema`
This commit is contained in:
commit
4abd389ef7
@ -515,19 +515,21 @@ def foreign_keys(table_name)
|
||||
|
||||
schema, name = extract_schema_qualified_name(table_name)
|
||||
|
||||
fk_info = select_all <<-SQL.strip_heredoc
|
||||
SELECT fk.referenced_table_name as 'to_table'
|
||||
,fk.referenced_column_name as 'primary_key'
|
||||
,fk.column_name as 'column'
|
||||
,fk.constraint_name as 'name'
|
||||
fk_info = select_all(<<-SQL.strip_heredoc, 'SCHEMA')
|
||||
SELECT fk.referenced_table_name AS 'to_table',
|
||||
fk.referenced_column_name AS 'primary_key',
|
||||
fk.column_name AS 'column',
|
||||
fk.constraint_name AS 'name',
|
||||
rc.update_rule AS 'on_update',
|
||||
rc.delete_rule AS 'on_delete'
|
||||
FROM information_schema.key_column_usage fk
|
||||
WHERE fk.referenced_column_name is not null
|
||||
JOIN information_schema.referential_constraints rc
|
||||
USING (constraint_schema, constraint_name)
|
||||
WHERE fk.referenced_column_name IS NOT NULL
|
||||
AND fk.table_schema = #{quote(schema)}
|
||||
AND fk.table_name = #{quote(name)}
|
||||
SQL
|
||||
|
||||
create_table_info = create_table_info(table_name)
|
||||
|
||||
fk_info.map do |row|
|
||||
options = {
|
||||
column: row['column'],
|
||||
@ -535,8 +537,8 @@ def foreign_keys(table_name)
|
||||
primary_key: row['primary_key']
|
||||
}
|
||||
|
||||
options[:on_update] = extract_foreign_key_action(create_table_info, row['name'], "UPDATE")
|
||||
options[:on_delete] = extract_foreign_key_action(create_table_info, row['name'], "DELETE")
|
||||
options[:on_update] = extract_foreign_key_action(row['on_update'])
|
||||
options[:on_delete] = extract_foreign_key_action(row['on_delete'])
|
||||
|
||||
ForeignKeyDefinition.new(table_name, row['to_table'], options)
|
||||
end
|
||||
@ -891,12 +893,10 @@ def column_definitions(table_name) # :nodoc:
|
||||
end
|
||||
end
|
||||
|
||||
def extract_foreign_key_action(structure, name, action) # :nodoc:
|
||||
if structure =~ /CONSTRAINT #{quote_column_name(name)} FOREIGN KEY .* REFERENCES .* ON #{action} (CASCADE|SET NULL|RESTRICT)/
|
||||
case $1
|
||||
when 'CASCADE'; :cascade
|
||||
when 'SET NULL'; :nullify
|
||||
end
|
||||
def extract_foreign_key_action(specifier) # :nodoc:
|
||||
case specifier
|
||||
when 'CASCADE'; :cascade
|
||||
when 'SET NULL'; :nullify
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -579,7 +579,7 @@ def rename_index(table_name, old_name, new_name)
|
||||
end
|
||||
|
||||
def foreign_keys(table_name)
|
||||
fk_info = select_all <<-SQL.strip_heredoc
|
||||
fk_info = select_all(<<-SQL.strip_heredoc, 'SCHEMA')
|
||||
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
|
||||
FROM pg_constraint c
|
||||
JOIN pg_class t1 ON c.conrelid = t1.oid
|
||||
|
@ -103,3 +103,24 @@ def test_drop_temporary_table
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Mysql2AnsiQuotesTest < ActiveRecord::Mysql2TestCase
|
||||
def setup
|
||||
@connection = ActiveRecord::Base.connection
|
||||
@connection.execute("SET SESSION sql_mode='ANSI_QUOTES'")
|
||||
end
|
||||
|
||||
def teardown
|
||||
@connection.reconnect!
|
||||
end
|
||||
|
||||
def test_primary_key_method_with_ansi_quotes
|
||||
assert_equal "id", @connection.primary_key("topics")
|
||||
end
|
||||
|
||||
def test_foreign_keys_method_with_ansi_quotes
|
||||
fks = @connection.foreign_keys("lessons_students")
|
||||
assert_equal([["lessons_students", "students", :cascade]],
|
||||
fks.map {|fk| [fk.from_table, fk.to_table, fk.on_delete] })
|
||||
end
|
||||
end
|
||||
|
@ -275,18 +275,6 @@ def test_collectly_dump_composite_primary_key
|
||||
end
|
||||
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase
|
||||
self.use_transactional_tests = false
|
||||
|
||||
def test_primary_key_method_with_ansi_quotes
|
||||
con = ActiveRecord::Base.connection
|
||||
con.execute("SET SESSION sql_mode='ANSI_QUOTES'")
|
||||
assert_equal "id", con.primary_key("topics")
|
||||
ensure
|
||||
con.reconnect!
|
||||
end
|
||||
end
|
||||
|
||||
class PrimaryKeyBigintNilDefaultTest < ActiveRecord::TestCase
|
||||
include SchemaDumpingHelper
|
||||
|
||||
|
@ -409,6 +409,14 @@
|
||||
t.references :student
|
||||
end
|
||||
|
||||
create_table :students, force: true do |t|
|
||||
t.string :name
|
||||
t.boolean :active
|
||||
t.integer :college_id
|
||||
end
|
||||
|
||||
add_foreign_key :lessons_students, :students, on_delete: :cascade
|
||||
|
||||
create_table :lint_models, force: true
|
||||
|
||||
create_table :line_items, force: true do |t|
|
||||
@ -777,12 +785,6 @@
|
||||
t.integer :lock_version, null: false, default: 0
|
||||
end
|
||||
|
||||
create_table :students, force: true do |t|
|
||||
t.string :name
|
||||
t.boolean :active
|
||||
t.integer :college_id
|
||||
end
|
||||
|
||||
create_table :subscribers, force: true, id: false do |t|
|
||||
t.string :nick, null: false
|
||||
t.string :name
|
||||
@ -1002,7 +1004,6 @@
|
||||
end
|
||||
|
||||
add_foreign_key :fk_test_has_fk, :fk_test_has_pk, column: "fk_id", name: "fk_name", primary_key: "pk_id"
|
||||
add_foreign_key :lessons_students, :students
|
||||
end
|
||||
|
||||
create_table :overloaded_types, force: true do |t|
|
||||
|
Loading…
Reference in New Issue
Block a user