aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb
diff options
context:
space:
mode:
authorRafael França <rafaelmfranca@gmail.com>2017-03-27 17:24:27 -0400
committerGitHub <noreply@github.com>2017-03-27 17:24:27 -0400
commitc1faca6333abe4b938b98fedc8d1f47b88209ecf (patch)
tree6ae0cf29da8404bf063e9d6cf36bbf718867f32a /activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb
parent8c658a0ecc7f2b5fc015d424baf9edf6f3eb2b0b (diff)
parentef6391d4537d9ff1ce46da786a1fccccd886e246 (diff)
downloadrails-c1faca6333abe4b938b98fedc8d1f47b88209ecf.tar.gz
rails-c1faca6333abe4b938b98fedc8d1f47b88209ecf.tar.bz2
rails-c1faca6333abe4b938b98fedc8d1f47b88209ecf.zip
Merge pull request #27636 from mtsmfm/disable-referential-integrity-without-superuser-privilege-take-2
Use `SET CONSTRAINTS` for `disable_referential_integrity` without superuser privileges (take 2)
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb')
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb47
1 files changed, 43 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb b/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb
index 44a7338bf5..730e7c7137 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb
@@ -6,8 +6,50 @@ module ActiveRecord
true
end
- def disable_referential_integrity # :nodoc:
+ def disable_referential_integrity(&block) # :nodoc:
if supports_disable_referential_integrity?
+ if supports_alter_constraint?
+ disable_referential_integrity_with_alter_constraint(&block)
+ else
+ disable_referential_integrity_with_disable_trigger(&block)
+ end
+ else
+ yield
+ end
+ end
+
+ private
+
+ def disable_referential_integrity_with_alter_constraint
+ tables_constraints = execute(<<-SQL).values
+ SELECT table_name, constraint_name
+ FROM information_schema.table_constraints
+ WHERE constraint_type = 'FOREIGN KEY'
+ AND is_deferrable = 'NO'
+ SQL
+
+ execute(
+ tables_constraints.collect { |table, constraint|
+ "ALTER TABLE #{quote_table_name(table)} ALTER CONSTRAINT #{constraint} DEFERRABLE"
+ }.join(";")
+ )
+
+ begin
+ transaction do
+ execute("SET CONSTRAINTS ALL DEFERRED")
+
+ yield
+ end
+ ensure
+ execute(
+ tables_constraints.collect { |table, constraint|
+ "ALTER TABLE #{quote_table_name(table)} ALTER CONSTRAINT #{constraint} NOT DEFERRABLE"
+ }.join(";")
+ )
+ end
+ end
+
+ def disable_referential_integrity_with_disable_trigger
original_exception = nil
begin
@@ -39,10 +81,7 @@ Rails needs superuser privileges to disable referential integrity.
end
rescue ActiveRecord::ActiveRecordError
end
- else
- yield
end
- end
end
end
end