提交 7b7b7c5c 编写于 作者: R Ryuta Kamizono

Extract foreign key action from `information_schema`

Fixes #25300.
上级 16bb3d6f
......@@ -516,18 +516,20 @@ def foreign_keys(table_name)
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 @@ 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
......
......@@ -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|
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册