From: | "David Johnston" <polobo(at)yahoo(dot)com> |
---|---|
To: | <pgsql-general(at)postgresql(dot)org> |
Subject: | Hidden Risk w/ UPDATE Cascade and Trigger-Based Validation |
Date: | 2011-06-03 00:26:48 |
Message-ID: | 034d01cc2184$ed77e8c0$c867ba40$@yahoo.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
Hi,
I am trying to get a better understanding of how the following Foreign Keys
with Update Cascades and validation trigger interact. The basic setup is a
permission table where the two permission parts share a common
"group/parent" which is embedded into their id/PK and which change via the
FK cascade mechanism. Rest of my thoughts and questions follow the setup.
I have the following schema (parts omitted/simplified for brevity since
everything works as expected)
CREATE TABLE userstorepermission (
userid text NOT NULL FK UPDATE CASCADE,
storeid text NOT NULL FK UPDATE CASCADE,
PRIMARY KEY (userid, storeid)
);
FUNCTION validate() RETURNS trigger AS
SELECT groupid FROM store WHERE storeid = [NEW.storeid] INTO storegroup
SELECT groupid FROM user WHERE userid = [NEW.userid] INTO usergroup
RAISE NOTICE 'Validating User Store Permission U:%;%, S:%;%', NEW.userid,
usergroup, NEW.storeid, storegroup;
IF (usergroup <> storegroup) THEN
RAISE NOTICE 'Disallow';
RETURN null;
ELSE
RAISE NOTICE 'Allow';
RETURN NEW;
END;
CREATE TRIGGER INSERT OR UPDATE EXECUTE validate();
Basically if I change the groupid both the userid and storeid values in
userstorepermission will change as well. This is desired. When I do update
the shared groupid the following NOTICES are raised from the validation
function above:
The change for groupid was TESTSGB -> TESTSGD:
NOTICE: Validating User Store Permission U:tester(at)TESTSGB;<NULL>
S:[TESTSGD]STORE01;TESTSGD [at this point apparently both user and store
have been updated and storeid in the permission table is being change]
CONTEXT: SQL statement "UPDATE ONLY "domain"."userstorepermission" SET
"s_id" = $1 WHERE $2 OPERATOR(pg_catalog.=) "s_id""
NOTICE: Allow
CONTEXT: SQL statement "UPDATE ONLY "domain"."userstorepermission" SET
"s_id" = $1 WHERE $2 OPERATOR(pg_catalog.=) "s_id""
NOTICE: Validating User Store Permission U:tester(at)TESTSGD;TESTSGD
S:[TESTSGD]STORE01;TESTSGD [and now the userid in the permission table gets
its turn]
CONTEXT: SQL statement "UPDATE ONLY "domain"."userstorepermission" SET
"u_id" = $1 WHERE $2 OPERATOR(pg_catalog.=) "u_id""
NOTICE: Allow
CONTEXT: SQL statement "UPDATE ONLY "domain"."userstorepermission" SET
"u_id" = $1 WHERE $2 OPERATOR(pg_catalog.=) "u_id""
The end result is that both values are changed as desired but the notices,
while they indirectly make sense (only one of the values can be update
cascaded at a time), are somewhat confusing and thus I am not sure if I am
possibly missing something that could eventually blow up in my face. I
expect other similar situations will present themselves in my model so I
want to get more understanding on at least whether what I am doing is safe
and ideally whether the CASCADE rules possibly relax intra-process
enforcement of constraints in order to allow this kind of multi-column key
update to succeed.
I see BUG #5505 from January of last year where Tom confirms that the
trigger will fire but never addresses the second point about the referential
integrity check NOT FAILING since the example's table_2 contains a value not
present in table_1.
Conceptually, as long as I consistently update ALL the relevant FKs the
initial and resulting state should remain consistent but only with a
different value. I'll probably do some more playing with "missing" a FK
Update Cascade and see whether the proper failures occurs but regardless
some thoughts and/or pointers are welcomed.
Thanks,
David J.
From | Date | Subject | |
---|---|---|---|
Next Message | tomas | 2011-06-03 05:15:40 | Re: Need suggestion |
Previous Message | Derrick Rice | 2011-06-02 21:16:52 | Re: invalid byte sequence for encoding "UTF8" |