Re: What have I done!?!?!? :-) - Mailing list pgsql-general

From Perry Smith
Subject Re: What have I done!?!?!? :-)
Date
Msg-id E62EA153-1EFD-411D-9553-5F890FC5139D@easesoftware.com
Whole thread Raw
In response to Re: What have I done!?!?!? :-)  (Jan Wieck <jan@wi3ck.info>)
Responses Re: What have I done!?!?!? :-)  (Magnus Hagander <magnus@hagander.net>)
List pgsql-general


On Apr 8, 2022, at 07:47, Jan Wieck <jan@wi3ck.info> wrote:

On 4/8/22 01:57, Nikolay Samokhvalov wrote:
On Thu, Apr 7, 2022 at 8:10 AM Jan Wieck <jan@wi3ck.info <mailto:jan@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

The above would only be used during testing.

For this project, I wondered if it was in the AR code base and found a method with the same name.  Note that my method was all done under one transaction.  The code they have uses multiple transactions.  I’m curious to know if either method is better / safer.

For the longest time, the Rails developers refused to put constraints into the DB insisting that the app could do it.  Eventually (SURPRISE!!!!) they were proven wrong.  Users can now add foreign key constraints using native AR constructs as well as general check constraints and indexes.  Before it had to be done using SQL.  Rails did have a general purpose “execute” statement (shown above).

Attachment

pgsql-general by date:

Previous
From: Magnus Hagander
Date:
Subject: Re: What have I done!?!?!? :-)
Next
From: Magnus Hagander
Date:
Subject: Re: What have I done!?!?!? :-)