Re: a trigger question - Mailing list pgsql-general

From Jan Wieck
Subject Re: a trigger question
Date
Msg-id 200206061937.g56Jbur27426@saturn.janwieck.net
Whole thread Raw
In response to a trigger question  (pblunat <pblunat@ujf-grenoble.fr>)
List pgsql-general
Zhou, Lixin wrote:
> Thanks Jan!
>
> >> 1) Fire the trigger AFTER INSERT.  BEFORE INSERT won't work.
> >> 2) Deferrable does not seem to be important.
>
> >Jan    1) Fire the trigger BEFORE INSERT does work
> >Jan    2) If you make the constraint deferred
> >Jan    3) And let the trigger return NEW instead of NULL;
>
> This is a really interesting trick!

    To  return  NEW?  The documented behaviour of a trigger fired
    BEFORE INSERT and returning NULL is, that the INSERT  doesn't
    take place. That pretty much guarantees that the key will not
    be there, wouldn't it?

>
> >> I've tested above, it does work as expected for PK/FKs that are integers.
>
> >Jan    It also works for all other types of keys.
>
> Yes, it should as I pointed out in another email.
>
> I had troubles because I used quot_literal on a new.varchar value within the
> PLPGSQL function.  This should cause SQL syntax error (eg: insert into
> tbl(a_string) values (''this is a string to be inserted but it will fail to
> insert.'') but I got the error message as "referential integrity error"
> instead of SQL syntax error.

    It should not, because those statements don't get parsed that
    way.   PL/pgSQL  is  not  a  string substitution/reevaluation
    system  like  some  other  scripting  languages.  Strings  in
    variables  are  handled  as  datum,  no  matter  if there are
    special characters in them or not.

    The statement

        INSERT INTO second_tbl (v) VALUES (new.v);

    Get's internally modified by the PL/pgSQL parser into

        INSERT INTO second_tbl (v) VALUES ( $1 );

    This $1 notation is only available via  the  internal  server
    programming   interface  (SPI)  and  PL/pgSQL  specifies  the
    datatype of that "parameter" explicitly in an array that  has
    to be passed to SPI_prepare().

    The  datatype (varchar(20) in our case) is known, because all
    this happens on the first trigger invocation and the  trigger
    system  passes  not  only the NEW row for first_tbl in, but a
    row descriptor as well.

    Surrounding new.v now with the function call  quote_literal()
    just add's the quoting to the string and inserts that result.
    Which  is  of  course  different  from  the  key   originally
    inserted,  and  if  you  started  off  with empty tables it's
    nearly impossible that this quoted string  exists  as  a  key
    (it's insertion should've failed because of the double qouted
    key missing ... and so forth ... maybe  we  could  start  off
    with  a  key  consisting  of single quotes only and work down
    from there, but that's academic and  not  exactly  what  your
    business modell requires).


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #



pgsql-general by date:

Previous
From: "Joshua b. Jore"
Date:
Subject: Re: How do I install Postgre on Windows NT?
Next
From: Neil Conway
Date:
Subject: Re: how to remove columns from a table