On Fri, Apr 8, 2022 at 3:23 PM Perry Smith <p...@easesoftware.com> wrote:

>
>
> On Apr 8, 2022, at 07:47, Jan Wieck <j...@wi3ck.info> wrote:
>
> On 4/8/22 01:57, Nikolay Samokhvalov wrote:
>
> On Thu, Apr 7, 2022 at 8:10 AM Jan Wieck <j...@wi3ck.info <
> mailto:j...@wi3ck.info <j...@wi3ck.info>>> wrote:
>    So **IF** Active Record is using that feature, then it can dump any
>    amount of garbage into your PostgreSQL database and PostgreSQL will
>    happily accept it with zero integrity checking.
> It's DISABLE TRIGGER ALL
> https://github.com/rails/rails/blob/831031a8cec5bfe59ef653ae2857d4fe64c5698d/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb#L12
> <
> https://github.com/rails/rails/blob/831031a8cec5bfe59ef653ae2857d4fe64c5698d/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb#L12
> >
>
>
> Similar poison, same side effect.
>
> Looking further at that code it also directly updates the PostgreSQL
> system catalog. This is a big, red flag.
>
> Why do the Rails developers think they need a sledgehammer like that? It
> seems to be doing that for over 7 years, so it is hard to tell from the
> commit log why they need to disable RI at all.
>
>
> It has been a long time since I’ve done Rails stuff.  What follows is the
> best I can recall but please take it with a grain of salt.
>
> The first problem is that generally Rails does not put constraints in the
> database.  There were others like me who thought that was insane and would
> put constraints in the database — this includes foreign key constraints,
> check constraints, etc.  About the only constraint that could be added into
> the DB using native Rails was the “not null” constraint.
>
> When foreign and other constraints were added, it broke something they
> call “Fixtures” which are present db states that are plopped into the DB
> during testing.  To “fix” that, I (and others) would add this into our code
> base: (I’m adding this to see what you guys think of it — is it safer /
> better or just as insane?)
>
>       def disable_referential_integrity(&block)
>         transaction {
>           begin
>             execute "SET CONSTRAINTS ALL DEFERRED"
>             yield
>           ensure
>             execute "SET CONSTRAINTS ALL IMMEDIATE"
>           end
>         }
>       end
>

This is perfectly normal code and nothing wrong with it. DEFERRED
constraints are how you are *supposed* to handle such things. It defers the
check of the foreign key to the end of the transaction, but it will still
fail to commit if the foreign key is broken *at that point*. But it lets
you do things like modify multiple tables that refer to each other, and
have the changes only checked when they're all done.


-- 
 Magnus Hagander
 Me: https://www.hagander.net/ <http://www.hagander.net/>
 Work: https://www.redpill-linpro.com/ <http://www.redpill-linpro.com/>

Reply via email to