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:
Eileen M. Uchitelle 2016-07-01 11:30:40 -04:00 committed by GitHub
commit 4abd389ef7
5 changed files with 46 additions and 36 deletions

@ -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|