1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Extract foreign key action from information_schema

Fixes #25300.
This commit is contained in:
Ryuta Kamizono 2016-06-07 06:26:49 +09:00
parent 16bb3d6f12
commit 7b7b7c5ce6
4 changed files with 44 additions and 34 deletions

View file

@ -516,18 +516,20 @@ module ActiveRecord
schema, name = extract_schema_qualified_name(table_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'
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 @@ module ActiveRecord
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 @@ module ActiveRecord
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

View file

@ -103,3 +103,24 @@ module ActiveRecord
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

View file

@ -275,18 +275,6 @@ class CompositePrimaryKeyTest < ActiveRecord::TestCase
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

View file

@ -409,6 +409,14 @@ ActiveRecord::Schema.define do
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 @@ ActiveRecord::Schema.define do
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 @@ ActiveRecord::Schema.define do
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|