Re: What have I done!?!?!? :-) - Mailing list pgsql-general
From | Jan Wieck |
---|---|
Subject | Re: What have I done!?!?!? :-) |
Date | |
Msg-id | 91e71bb4-6b6e-a4e1-1456-b9a9495f7e0d@wi3ck.info Whole thread Raw |
In response to | What have I done!?!?!? :-) (Perry Smith <pedz@easesoftware.com>) |
Responses |
Re: What have I done!?!?!? :-)
|
List | pgsql-general |
On 4/8/22 09:27, Magnus Hagander wrote: > > > On Fri, Apr 8, 2022 at 3:23 PM Perry Smith <pedz@easesoftware.com > <mailto:pedz@easesoftware.com>> wrote: > 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. Indeed, especially because this code does not require any elevated permissions, guarantees referential integrity at commit time and guarantees that no inconsistent, intermediate state will ever be visible to another, concurrent session. It only affects constraints that have been declared DEFERRABLE. Those that are not are silently ignored (as per SQL standard). A lot of frameworks didn't support foreign keys because one of the most popular databases at that time didn't support them. Well, the SQL parser of that particular database would accept the syntax, but the engine would not enforce anything. Even the manual of that database stated that "foreign keys are mostly for documentation purposes and are not needed as long as the application does all operations in the correct order." They changed that part of the documentation when support for InnoDB was added. Therefore I would not put all blame on the Rails developers. Best Regards, Jan
pgsql-general by date: