Re: Calling functions from Delete View (+ contrib/pgcrypto) = madness ?? - Mailing list pgsql-sql

From Jim Buttafuoco
Subject Re: Calling functions from Delete View (+ contrib/pgcrypto) = madness ??
Date
Msg-id 20050325034203.M80271@contactbda.com
Whole thread Raw
In response to Calling functions from Delete View (+ contrib/pgcrypto) = madness ??  ("Moran.Michael" <Michael.Moran@IGT.com>)
List pgsql-sql
Mike, 

I posted this RULE also on hackers


CREATE or replace RULE crypto_view_delete_rule
AS ON DELETE
TO crypto_view
DO INSTEAD
(
select func_delFromCrypto( OLD.id,OLD.crypted_content);
);


Jim


---------- Original Message -----------
From: "Moran.Michael" <Michael.Moran@IGT.com>
To: pgsql-sql@postgresql.org
Sent: Thu, 24 Mar 2005 17:30:33 -0800
Subject: [SQL] Calling functions from Delete View (+ contrib/pgcrypto) = madness ??

> Hello there,
> 
> I have a View with a Delete rule and I would like the Delete rule to call a
> function (and pass-in a few of the the underlying View's/Table's column
> values). How do you do this?
> 
> When I do it, I keep getting the following error:
> ERROR:  function expression in FROM may not refer to other relations of same
> query level
> 
> This is my new Delete View that attempts to call a Function but yields the
> above-mentioned error:
> 
> CREATE RULE crypto_view_delete_rule
> AS ON DELETE
> TO crypto_view
> DO INSTEAD
>     --Original (working) code:
>     --  DELETE FROM crypto
>     -- WHERE id = OLD.id;
> 
>     --NEW (non-working) code:
>     select * from func_delFromCrypto( crypto.id, encode( decrypt(
> crypto.crypted_content, decode ('password'::text, 'escape'::text),
> 'aes'::text), 'escape'::text) );
> 
> The above may seem complicated, but the crypto portion DOES work (as you'll
> see below), and I've broken down the steps below so that it's easy to see
> what's going on:
> 
> 1. Imagine the following simple table:
> 
> CREATE TABLE crypto (
>     id SERIAL PRIMARY KEY,
>     title VARCHAR(50),
>     crypted_content BYTEA
> );
> 
> 2. Imagine the following simple working View:
> 
> CREATE VIEW crypto_view AS
>   SELECT
>     id,
>     title,
>     --Decrypt the BYTEA column and convert result to TEXT type:
>     encode(decrypt(crypted_content, decode('password','escape'::text),
> 'aes'::text), 'escape'::text) as crypted_content
>   FROM
>     crypto;
> 
> 3. Imagine my original, simple Delete Rule (that works -- it was my original
> version prior to changing it to call the Function):
> 
> CREATE RULE crypto_view_delete_rule
> AS ON DELETE
> TO crypto_view
> DO INSTEAD
>     DELETE FROM crypto
>     WHERE id = OLD.id;
> 
> 4. Let's load (and encrypt) some test data into the above-mentioned table:
> 
> insert into crypto VALUES (1, 'test1', encrypt('11112222', 'password',
> 'aes') );
> insert into crypto VALUES (2, 'test2', encrypt('22223333', 'password',
> 'aes') );
> insert into crypto VALUES (3, 'test3', encrypt('33334444', 'password',
> 'aes') );
> insert into crypto VALUES (4, 'test4', encrypt('44445555', 'password',
> 'aes') );
> insert into crypto VALUES (5, 'test5', encrypt('55556666', 'password',
> 'aes') );
> 
> 5. Let's SELECT from the table to see its contents (note the encrypted
> values):
> 
> select * from crypto;
>  id | title |                      crypted_content
> ----+-------+------------------------------------------------------------
>   1 | test1 | \026\206I93\327\315\376t\243\006~J\177{\301
>   2 | test2 | \257\212\260\321\217\274c\210d \361\225\212\327\317\206
>   3 | test3 | 6\345:\224dp\002\206<\007k\344\302\347V\214
>   4 | test4 | VH)\023\303\0239\363\323\362\22734\204R\357
>   5 | test5 | \216Np\235\026\362\277\246\026\027\221\266\021\361\224\256
> (5 rows)
> 
> 6. Let's run the View (which nicely decrypts the encrypted columns):
> 
> # select * from crypto_view;
>  id | title | crypted_content
> ----+-------+-----------------
>   1 | test1 | 11112222
>   2 | test2 | 22223333
>   3 | test3 | 33334444
>   4 | test4 | 44445555
>   5 | test5 | 55556666
> (5 rows)
> 
> 7. Let's test the old DELETE RULE (the one that doesn't call a function,
> hence works):
> 
> delete from crypto_view where crypted_content = 55556666;
> DELETE 1
> 
> Check that the DELETE RULE worked (there is one less row of data now):
> # select * from crypto_view;
>  id | title | crypted_content
> ----+-------+-----------------
>   1 | test1 | 11112222
>   2 | test2 | 22223333
>   3 | test3 | 33334444
>   4 | test4 | 44445555
> (4 rows)
> 
> It works! Pretty straight forward, right?
> 
> Now let's make things a little more interesting...
> 
> 8. Now here is the following (working) function that I want my rule to call:
> 
> CREATE OR REPLACE FUNCTION func_delFromCrypto(INTEGER, VARCHAR)
> RETURNS INTEGER
> AS '
> DECLARE
>     _id             ALIAS FOR $1;
>     _crypto_data    ALIAS FOR $2;
>     ret             INTEGER:=0;
> BEGIN
>     DELETE FROM crypto WHERE id = _id AND encode( decrypt( crypted_content,
> decode(''password''::text, ''escape''::text), ''aes''::text),
> ''escape''::text) = _crypto_data;
>     GET DIAGNOSTICS ret = ROW_COUNT;
>     RETURN ret;
> END;
> ' LANGUAGE 'plpgsql';
> 
> 9. The function works, stand-alone, as you can see below:
> 
> # select * from func_delFromCrypto(4, '44445555');
>  func_delfromcrypto
> --------------------
>                   1
> (1 row)
> 
> Check the output (there is one less row now):
> 
> # select * from crypto_view;
>  id | title | crypted_content
> ----+-------+-----------------
>   1 | test1 | 11112222
>   2 | test2 | 22223333
>   3 | test3 | 33334444
> (3 rows)
> 
> So the function works, stand-alone. But how can I get my Delete Rule to call
> it?
> 
> I want my Delete Rule to pass in the underlying ID (the primary key) and the
> crypted_content into the Function (like you can when calling the Function
> stand-alone).
> 
> Once again, here is my new DELETE RULE that calls the function (and fails):
> 
> CREATE RULE crypto_view_delete_rule
> AS ON DELETE
> TO crypto_view
> DO INSTEAD
>     --Original (working) code:
>     --  DELETE FROM crypto
>     -- WHERE id = OLD.id;
> 
>     --NEW (non-working) code:
>     select * from func_delFromCrypto( crypto.id, encode( decrypt(
> crypto.crypted_content, decode ('password'::text, 'escape'::text),
> 'aes'::text), 'escape'::text) );
> 
> I suspect there is a syntax error or something, as I don't have access to
> the underlying colums "crypto.id" and "crypto.crypted_content". Any help is
> greatly appreciated.
> 
> Thank you kindly in advance,
> 
> Michael Moran
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 9: the planner will ignore your desire to choose an index scan if your
>       joining column's datatypes do not match
------- End of Original Message -------



pgsql-sql by date:

Previous
From: "Moran.Michael"
Date:
Subject: Calling functions from Delete View (+ contrib/pgcrypto) = madness ??
Next
From: "Moran.Michael"
Date:
Subject: Re: Calling functions from Delete View (+ contrib/pgcrypto)