Module: ActiveRecord::ConnectionAdapters::PostgreSQL::ReferentialIntegrity
Do not use. This module is for internal use only.
| Relationships & Source Files | |
| Extension / Inclusion / Inheritance Descendants | |
|
Included In:
| |
| Defined in: | activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb |
Instance Method Summary
- #check_all_foreign_keys_valid!
- #disable_referential_integrity(&block)
-
#enforced_foreign_keys(current_schemas_only: false)
private
conparentid = 0: a partition's child copy can't be ALTERed; the parent's ALTER cascades.
- #set_foreign_key_enforcement(fk, enforced:) private
- #toggle_foreign_key_enforcement(current_schemas_only: false) private
Instance Method Details
#check_all_foreign_keys_valid!
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb', line 45
def check_all_foreign_keys_valid! # :nodoc: if supports_enforced_foreign_keys? toggle_foreign_key_enforcement else sql = <<~SQL do $$ declare r record; BEGIN FOR r IN ( SELECT FORMAT( 'UPDATE pg_catalog.pg_constraint SET convalidated=false WHERE conname = ''%1$I'' AND connamespace::regnamespace = ''%2$I''::regnamespace AND conrelid::regclass = ''%3$I''::regclass; ALTER TABLE %2$I.%3$I VALIDATE CONSTRAINT %1$I;', constraint_name, table_schema, table_name ) AS constraint_check FROM information_schema.table_constraints tc WHERE tc.constraint_type = 'FOREIGN KEY' ) LOOP EXECUTE (r.constraint_check); END LOOP; END; $$; SQL transaction(requires_new: true) do execute(sql) end end end
#disable_referential_integrity(&block)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb', line 7
def disable_referential_integrity(&block) # :nodoc: if supports_enforced_foreign_keys? toggle_foreign_key_enforcement(current_schemas_only: true, &block) else original_exception = nil begin transaction(requires_new: true) do execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";")) end rescue ActiveRecord::ActiveRecordError => e original_exception = e end begin yield rescue ActiveRecord::InvalidForeignKey => e warn <<~WARNING WARNING: Rails was not able to disable referential integrity. This is most likely caused due to missing permissions. The user must be superuser to execute DISABLE TRIGGER ALL. cause: #{original_exception&.} WARNING raise e end begin transaction(requires_new: true) do execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";")) end rescue ActiveRecord::ActiveRecordError end end end
#enforced_foreign_keys(current_schemas_only: false) (private)
conparentid = 0: a partition's child copy can't be ALTERed; the parent's ALTER cascades
# File 'activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb', line 78
def enforced_foreign_keys(current_schemas_only: false) query_all(<<~SQL) SELECT n.nspname AS schema_name, t.relname AS table_name, c.conname AS constraint_name FROM pg_constraint c JOIN pg_class t ON c.conrelid = t.oid JOIN pg_namespace n ON c.connamespace = n.oid WHERE c.contype = 'f' AND c.conenforced = true AND c.conparentid = 0 AND pg_catalog.pg_has_role(t.relowner, 'USAGE') #{"AND n.nspname = ANY (current_schemas(false))" if current_schemas_only} SQL end
#set_foreign_key_enforcement(fk, enforced:) (private)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb', line 104
def set_foreign_key_enforcement(fk, enforced:) table = "#{quote_column_name(fk["schema_name"])}.#{quote_column_name(fk["table_name"])}" execute("ALTER TABLE #{table} ALTER CONSTRAINT #{quote_column_name(fk["constraint_name"])} " \ "#{enforced ? "ENFORCED" : "NOT ENFORCED"}") end
#toggle_foreign_key_enforcement(current_schemas_only: false) (private)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb', line 92
def toggle_foreign_key_enforcement(current_schemas_only: false) fks = enforced_foreign_keys(current_schemas_only: current_schemas_only) transaction(requires_new: true) do fks.each { |fk| set_foreign_key_enforcement(fk, enforced: false) } yield if block_given? fks.each { |fk| set_foreign_key_enforcement(fk, enforced: true) } end end