Thread: Adding the optional clause 'AS' in CREATE TRIGGER

Adding the optional clause 'AS' in CREATE TRIGGER

From
"Okano, Naoki"
Date:
Hi, 

I would like to add the following support for a trigger. 
This implementation enables to create a trigger efficiently 
in single command. 

It had been discussed before. The link is as shown below.
https://www.postgresql.org/message-id/CAA-aLv4m%3Df9cc1zcUzM49pE8%2B2NpytUDraTgfBmkTOkMN_wO2w%40mail.gmail.com

Currently, PostgreSQL requires two steps to create a trigger.
1. to create a function.
2. to define a trigger with action specified via already created function.

Supporting 'AS' clause in CREATE TRIGGER syntax will enable the option of 
defining the trigger in single command.
As a bonus, it will be compatible with oracle.

Also, the optional clause 'OR REPLACE' is required as below.
https://www.postgresql.org/message-id/CAA-aLv6KYgVt2CwaRdcnptzWVngEm72Cp4mUFnF-MfeH0gS91g%40mail.gmail.com

Currently, to change the definition of a trigger, trigger needs to 
be dropped first before creating it again with new definition.
To change the definition of a function in CREATE TRIGGER syntax,
trigger needs to be dropped first before creating it again with new definition, too! 
So, we need to add the optional clause 'OR REPLACE'.

Adding the optional clauses 'AS' and 'OR REPLACE' in CREATE TRIGGER syntax gives
the comfort of defining the trigger or redefining the trigger definition 
which contains the function definition in single command. 

Here is the syntax based on the previous discussion.  

CREATE [ OR REPLACE ] [ CONSTRAINT ]  TRIGGER name { BEFORE | AFTER | INSTEAD OF }    { event [ OR ... ] }   ON
table_name  [ FROM referenced_table_name ]   [ NOT DEFERRABLE | [ DEFERRABLE ] { INITIALLY IMMEDIATE | INITIALLY
DEFERRED} ]   [ FOR [ EACH ] { ROW | STATEMENT } ]   [ WHEN ( condition ) ]   { EXECUTE PROCEDURE function_name (
arguments)     | AS 'trigger function definition' [ LANGUAGE lang_name ]       [ SET configuration_parameter { TO value
|= value | FROM CURRENT }]   }
 

If you have your opinion on this concept, please give me it. 

Regards, 
Okano Naoki 
Fujitsu  



Re: Adding the optional clause 'AS' in CREATE TRIGGER

From
Tom Lane
Date:
"Okano, Naoki" <okano.naoki@jp.fujitsu.com> writes:
> I would like to add the following support for a trigger.
> This implementation enables to create a trigger efficiently
> in single command.

> It had been discussed before. The link is as shown below.
> https://www.postgresql.org/message-id/CAA-aLv4m%3Df9cc1zcUzM49pE8%2B2NpytUDraTgfBmkTOkMN_wO2w%40mail.gmail.com

I think people pretty much lost interest in that proposal, which is
why it never got finished.  Aside from the definitional issues discussed
in that thread, I can think of a few other problems:

1. The impression I have is that most people write trigger functions
so that they can be shared across multiple uses.  That'd be impossible
with anonymous trigger function blocks.  So you'd be trading off merging
two commands into one, versus having to write out the whole body of the
trigger multiple times, which wouldn't be much of a win.

2. I am concerned that every time we add any syntax to CREATE FUNCTION,
we'll have to think about whether we need to add it to CREATE TRIGGER.
(Or more likely, we'll forget and then users will complain.)

3. There's a lot of infrastructure that's built up around CREATE FUNCTION,
such as psql's \ef and \sf commands.  We'd soon find ourselves having to
duplicate all that for triggers.

So personally I feel that the value-for-work-expended ratio here is
pretty low.

But in any case it would be a serious mistake to do this without first
implementing CREATE OR REPLACE TRIGGER.  I think that's an entirely
separate proposal and you would be well advised to treat it as such.
It's far from trivial because of locking considerations.  You probably
have to take an exclusive lock on the owning relation in order to change
trigger properties.  (An advantage of the separate-function-definition
approach is that you can replace the function body with a much weaker
lock.)

> Supporting 'AS' clause in CREATE TRIGGER syntax will enable the option of
> defining the trigger in single command.
> As a bonus, it will be compatible with oracle.

It certainly would not match Oracle's syntax for trigger bodies.  It might
slightly reduce the conversion pain, but only slightly.
        regards, tom lane



Re: Adding the optional clause 'AS' in CREATE TRIGGER

From
"Okano, Naoki"
Date:
> But in any case it would be a serious mistake to do this without first 
> implementing CREATE OR REPLACE TRIGGER.  I think that's an entirely separate 
> proposal and you would be well advised to treat it as such.
I see. There are more problems than I expected...
Let me start with 'OR REPLACE' clause.

At least, adding only 'OR REPLACE' clause has the following advantages.
* It enables users to redefine a trigger in single command.
* The trigger can always be referenced when redefining a trigger. # But it is not so when using 'DROP' and 'CREATE'
commands.It is useful when users change the function or change the condition of 'WHEN' clause.
 

Regard,
Okano Naoki
Fujitsu



Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
"Okano, Naoki"
Date:
On Wednesday, November 16, 2016 4:31 PM Okano Naoki wrote:
> > But in any case it would be a serious mistake to do this without first 
> > implementing CREATE OR REPLACE TRIGGER.  I think that's an entirely separate 
> > proposal and you would be well advised to treat it as such.
> I see. There are more problems than I expected...
> Let me start with 'OR REPLACE' clause.
I tried to cretae a patch for CREATE OR REPLACE TRIGGER.
An example of execution is shown below.

example)
1.define a new trigger 
  CREATE TRIGGER regular_trigger
       AFTER UPDATE ON table_name
       REFERENCING OLD TABLE AS oldtable_1 NEW TABLE AS newtable_1
       FOR EACH STATEMENT
       EXECUTE PROCEDURE func_1();
2.redinfe a trigger in single command
 CREATE OR REPLACE TRIGGER regular_trigger
       AFTER UPDATE OR DELETE ON table_name
       REFERENCING OLD TABLE AS oldtable_2 NEW TABLE AS newtable_2
       FOR EACH ROW
       EXECUTE PROCEDURE func_2();

If the named trigger does not exist. 
a new trigger is also created by using OR REPLACE clause.
A regular trigger cannot be replaced by a constraint trigger and vice varsa.
because a constraint trigger has a different role from regular triger.

Please give me feedback.

Regards, 
Okano Naoki 
Fujitsu

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Attachment

Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
Robert Haas
Date:
On Tue, Feb 7, 2017 at 3:11 AM, Okano, Naoki <okano.naoki@jp.fujitsu.com> wrote:
> On Wednesday, November 16, 2016 4:31 PM Okano Naoki wrote:
>> > But in any case it would be a serious mistake to do this without first
>> > implementing CREATE OR REPLACE TRIGGER.  I think that's an entirely separate
>> > proposal and you would be well advised to treat it as such.
>> I see. There are more problems than I expected...
>> Let me start with 'OR REPLACE' clause.
> I tried to cretae a patch for CREATE OR REPLACE TRIGGER.
> An example of execution is shown below.
>
> example)
> 1.define a new trigger
>   CREATE TRIGGER regular_trigger
>        AFTER UPDATE ON table_name
>        REFERENCING OLD TABLE AS oldtable_1 NEW TABLE AS newtable_1
>        FOR EACH STATEMENT
>        EXECUTE PROCEDURE func_1();
> 2.redinfe a trigger in single command
>  CREATE OR REPLACE TRIGGER regular_trigger
>        AFTER UPDATE OR DELETE ON table_name
>        REFERENCING OLD TABLE AS oldtable_2 NEW TABLE AS newtable_2
>        FOR EACH ROW
>        EXECUTE PROCEDURE func_2();
>
> If the named trigger does not exist.
> a new trigger is also created by using OR REPLACE clause.
> A regular trigger cannot be replaced by a constraint trigger and vice varsa.
> because a constraint trigger has a different role from regular triger.
>
> Please give me feedback.

You should add this to the next CommitFest so it doesn't get missed.

https://commitfest.postgresql.org/

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
"Okano, Naoki"
Date:
On Thursday, February 9, 2017 4:41 AM Robert Haas wrote:
> You should add this to the next CommitFest so it doesn't get missed.
> 
> https://commitfest.postgresql.org/

Thank you for your kind advice!
I have added this patch to the CommitFest 2017-03. 

Regards,
Okano Naoki
Fujitsu

Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
Jim Nasby
Date:
On 11/14/16 8:51 PM, Tom Lane wrote:
> 1. The impression I have is that most people write trigger functions
> so that they can be shared across multiple uses.  That'd be impossible
> with anonymous trigger function blocks.  So you'd be trading off merging
> two commands into one, versus having to write out the whole body of the
> trigger multiple times, which wouldn't be much of a win.

I've fairly frequently needed one-off triggers, usually to do some kind 
of data validation that wasn't suitable in a CHECK constraint. Enough so 
that twice now[1] I've created generic trigger functions that allow you 
to specify an arbitrary expression to test against NEW and OLD.

1: Second, WIP example: 
https://github.com/decibel/tg_sanity/blob/master/sql/tg_sanity.sql
-- 
Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX
Experts in Analytics, Data Architecture and PostgreSQL
Data in Trouble? Get it in Treble! http://BlueTreble.com
855-TREBLE2 (855-873-2532)



Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
Peter Eisentraut
Date:
On 2/7/17 03:11, Okano, Naoki wrote:
> I tried to cretae a patch for CREATE OR REPLACE TRIGGER.

I have a feeling that this was proposed a few times in the ancient past
but did not go through because of locking issues.  I can't find any
emails about it through.  Does anyone remember?  Have you thought about
locking issues?

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
"Okano, Naoki"
Date:
Peter Eisentraut wrote:
> I have a feeling that this was proposed a few times in the ancient past
> but did not go through because of locking issues.  I can't find any
> emails about it through.  Does anyone remember?  Have you thought about
> locking issues?
Is this e-mail you are finding?
https://www.postgresql.org/message-id/20140916124537.GH25887%40awork2.anarazel.de

I am considering to add 'OR REPLACE' clause as a first step.
At least, I think there is no need to change the locking level when replacing a trigger with 'EXECUTE PROCEDURE'
clause.
In PostgreSQL, we currently have ShareRowExclusiveLock lock on relation on which trigger is created.
ShareRowExclusiveLockis enough to replace a trigger.
 
Also, we currently have RowExclusiveLock on pg_trigger. RowExclusiveLock is enough to replace a trigger, too.

Regards,
Okano Naoki
Fujitsu



Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
Peter Eisentraut
Date:
On 3/8/17 04:12, Okano, Naoki wrote:
> Peter Eisentraut wrote:
>> I have a feeling that this was proposed a few times in the ancient past
>> but did not go through because of locking issues.  I can't find any
>> emails about it through.  Does anyone remember?  Have you thought about
>> locking issues?
> Is this e-mail you are finding?
> https://www.postgresql.org/message-id/20140916124537.GH25887%40awork2.anarazel.de

No, that's not the one I had in mind.

> I am considering to add 'OR REPLACE' clause as a first step.
> At least, I think there is no need to change the locking level when replacing a trigger with 'EXECUTE PROCEDURE'
clause.
> In PostgreSQL, we currently have ShareRowExclusiveLock lock on relation on which trigger is created.
ShareRowExclusiveLockis enough to replace a trigger.
 
> Also, we currently have RowExclusiveLock on pg_trigger. RowExclusiveLock is enough to replace a trigger, too.

I'm not saying it's not correct.  I was just wondering.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
"Okano, Naoki"
Date:
Peter Eisentraut wrote:
> On 3/8/17 04:12, Okano, Naoki wrote:
> > Peter Eisentraut wrote:
> >> I have a feeling that this was proposed a few times in the ancient past
> >> but did not go through because of locking issues.  I can't find any
> >> emails about it through.  Does anyone remember?  Have you thought about
> >> locking issues?
> > Is this e-mail you are finding?
> > https://www.postgresql.org/message-id/20140916124537.GH25887%40awork2.anarazel.de
>
> No, that's not the one I had in mind.
I see. But I could only find it. 
Would anyone know e-mails discussed about locking issues? 

> > I am considering to add 'OR REPLACE' clause as a first step.
> > At least, I think there is no need to change the locking level when replacing a trigger with 'EXECUTE PROCEDURE'
clause.
> > In PostgreSQL, we currently have ShareRowExclusiveLock lock on relation on which trigger is created.
ShareRowExclusiveLockis enough to replace a trigger.
 
> > Also, we currently have RowExclusiveLock on pg_trigger. RowExclusiveLock is enough to replace a trigger, too.
> 
> I'm not saying it's not correct.  I was just wondering.
Thank you for your opinion!
I think we do not need to change locking level in this case.
If someone notice a mistake in my understanding, please point out it.

Regards,
Okano Naoki
Fujitsu



Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
Tom Lane
Date:
"Okano, Naoki" <okano.naoki@jp.fujitsu.com> writes:
> Peter Eisentraut wrote:
>>> I have a feeling that this was proposed a few times in the ancient past
>>> but did not go through because of locking issues.  I can't find any
>>> emails about it through.  Does anyone remember?  Have you thought about
>>> locking issues?

>>> Is this e-mail you are finding?
>>> https://www.postgresql.org/message-id/20140916124537.GH25887%40awork2.anarazel.de

>> No, that's not the one I had in mind.

That's still a thread well worth studying in detail.  It does touch on
locking issues, in that it points out that we allow you to replace a
trigger function's body with CREATE OR REPLACE FUNCTION with no lock at
all on the relation(s) it's a trigger for.  Even with very lax assumptions
about what lock level CREATE OR REPLACE TRIGGER needs, it can't match
"none".  Now you could certainly argue that we're not being very safe by
allowing trigger functions to be changed that way, but that's the current
state of affairs.

Another thread that you really need to absorb in its entirety is

https://www.postgresql.org/message-id/flat/5447578C.2050807%40proxel.se

and you might also want to read the older threads that Robert Haas
links to early in that thread.

The locking-related point that strikes me most forcefully in that thread
is the concerns about whether a concurrent pg_dump run will produce a
consistent view of the table's triggers.  This is problematic mainly
because pg_dump itself will see only the catalog entries that were current
when it started, but it relies heavily on ruleutils.c which will tend to
see committed changes immediately.  Now, the existing behavior here is
probably not at all perfect, but that doesn't mean it's okay to make
things worse with CREATE OR REPLACE TRIGGER.  A conservative conclusion
would be that C.O.R.T. needs to take AccessExclusiveLock so that it
can't run in parallel with pg_dump.  Maybe that can be relaxed but it
requires some study.  (CREATE TRIGGER doesn't have this issue because
pg_dump wouldn't see the new trigger at all and thus would never ask
ruleutils about it.)

Even if you don't care about pg_dump, I think that the question of whether
concurrent DML operations would always see (and act upon) instantaneously-
consistent versions of a table's trigger state is worth worrying about.
        regards, tom lane



Re: [HACKERS] Adding the optional clause 'AS' in CREATE TRIGGER

From
Surafel Temesgen
Date:

I am sending the review of this patch

I found the following

v  Use <optional> tage in documentation

v  Don’t modified existing test case add new one instead

v  Comment in pg_constraint.c is extended make it short

v  Error message can be more guider if it tells about general rule   

v  Wrong result in concurrency case

       Step to produce the result

1.       build with with --enable-cassert and with -DCATCACHE_FORCE_RELEASE=1

2.       Run these commands as setup:

      CREATE TABLE my_table1 (id integer, name text);

      CREATE TABLE my_table2 (id integer);

3.       CREATE FUNCTION my_deleteproc1() RETURNS trigger AS $$

                              begin

                              DELETE FROM my_table2 WHERE id=OLD.id;

                                  RETURN NULL;

                              end;$$ LANGUAGE plpgsql;

4.       INSERT INTO my_table1 VALUES(323, 'Alex');

                              INSERT INTO my_table1 VALUES(23, 'Teddy');

                              INSERT INTO my_table1 VALUES(38, 'Bob');

                              INSERT INTO my_table2 VALUES(323);

                              INSERT INTO my_table2 VALUES(23);

                              INSERT INTO my_table2 VALUES(38);

5.     CREATE OR REPLACE TRIGGER my_regular_trigger AFTER DELETE ON my_table1

                             FOR EACH ROW

                             EXECUTE PROCEDURE my_deleteproc1();

6.     Attach a debugger to your session set a breakpoint at ExecARDeleteTriggers

7.     Run this in your session

                             DELETE FROM my_table1 WHERE id=323;

8.     start another session and run:

                             CREATE OR REPLACE TRIGGER my_regular_trigger AFTER INSERT ON my_table1

                             FOR EACH ROW

                             EXECUTE PROCEDURE my_deleteproc1();

9.     exite the debugger to release the first session

     and the result

                             postgres=# SELECT * FROM my_table1;

                              id | name

                              ----+-------

                              23 | Teddy

                             38 | Bob

                             (2 rows)

                             postgres=# SELECT * FROM my_table2;

                             id 

                             -----

                             323

                             23

                             38

                            (3 rows)


                            Id number 323 should not be there in my_table2;

             

                Regards 

                Surafel

Re: Adding the optional clause 'AS' in CREATE TRIGGER

From
David Steele
Date:
Hi Naoki,

On 3/17/17 11:58 AM, Surafel Temesgen wrote:

> I am sending the review of this patch

This thread has been idle for a week.  Please respond and/or post a new 
patch by 2017-03-28 00:00 AoE (UTC-12) or this submission will be marked 
"Returned with Feedback".

-- 
-David
david@pgmasters.net



Re: Adding the optional clause 'AS' in CREATE TRIGGER

From
"Okano, Naoki"
Date:
Hi Surafel,
Thank you for your review!
But I have not finish fixing a patch yet.

> v  Use <optional> tage in documentation
ok. 

> v  Don’t modified existing test case add new one instead
These existing tests I modified are the results of commands "SELECT
pg_get_triggerdef(oid, true) ... ". 
I modified them in order to match with pg_get_functiondef(). 
The keyword 'OR REPLACE' is always added in CREATE FUNCTION. 
Does not it make sense?

> v  Comment in pg_constraint.c is extended make it short
> v  Error message can be more guider if it tells about general rule
ok. 

> v  Wrong result in concurrency case
Thank you for the detailed example case. I appreciate it.
The issue does not seem to be resolved easily because I have to 
modify pg_get_constraintdef_worker() in ruleutils.c.
And it takes some more time to modify pg_get_constraintdef_worker().

So, I am moving this patch to "Returned with Feedback".

Regards,
Okano Naoki
Fujitsu