From 88e785538d8a1fb9e7c007b46943de3dbd13675f Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 15 Aug 2018 23:08:34 +0200 Subject: [PATCH 3/3] Change PROCEDURE to FUNCTION in CREATE TRIGGER syntax Since procedures are now a different thing from functions, change the CREATE TRIGGER and CREATE EVENT TRIGGER syntax to use FUNCTION in the clause that specifies the function. PROCEDURE is still accepted for compatibility. pg_dump and ruleutils.c output is not changed yet, because that would require a change in information_schema.sql and thus a catversion change. --- doc/src/sgml/ddl.sgml | 2 +- doc/src/sgml/event-trigger.sgml | 4 ++-- doc/src/sgml/func.sgml | 6 +++--- doc/src/sgml/information_schema.sgml | 2 +- doc/src/sgml/lo.sgml | 2 +- doc/src/sgml/plperl.sgml | 4 ++-- doc/src/sgml/plpgsql.sgml | 16 +++++++-------- doc/src/sgml/pltcl.sgml | 4 ++-- doc/src/sgml/ref/create_event_trigger.sgml | 12 +++++++++-- doc/src/sgml/ref/create_trigger.sgml | 24 ++++++++++++++-------- doc/src/sgml/tcn.sgml | 2 +- doc/src/sgml/textsearch.sgml | 4 ++-- doc/src/sgml/trigger.sgml | 4 ++-- src/backend/parser/gram.y | 9 ++++++-- src/test/regress/expected/triggers.out | 4 ++-- src/test/regress/sql/triggers.sql | 4 ++-- 16 files changed, 62 insertions(+), 41 deletions(-) diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 6aa035188f..5ae3cacbf0 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -3580,7 +3580,7 @@ Example CREATE TRIGGER insert_measurement_trigger BEFORE INSERT ON measurement - FOR EACH ROW EXECUTE PROCEDURE measurement_insert_trigger(); + FOR EACH ROW EXECUTE FUNCTION measurement_insert_trigger(); We must redefine the trigger function each month so that it always diff --git a/doc/src/sgml/event-trigger.sgml b/doc/src/sgml/event-trigger.sgml index be975d1399..d273dc5b58 100644 --- a/doc/src/sgml/event-trigger.sgml +++ b/doc/src/sgml/event-trigger.sgml @@ -1044,7 +1044,7 @@ A Complete Event Trigger Example AS 'noddl' LANGUAGE C; CREATE EVENT TRIGGER noddl ON ddl_command_start - EXECUTE PROCEDURE noddl(); + EXECUTE FUNCTION noddl(); @@ -1129,7 +1129,7 @@ A Table Rewrite Event Trigger Example CREATE EVENT TRIGGER no_rewrite_allowed ON table_rewrite - EXECUTE PROCEDURE no_rewrite(); + EXECUTE FUNCTION no_rewrite(); diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index c6f61ce2c0..eaf8fbdf62 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -20594,7 +20594,7 @@ Trigger Functions CREATE TRIGGER z_min_update BEFORE UPDATE ON tablename -FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); +FOR EACH ROW EXECUTE FUNCTION suppress_redundant_updates_trigger(); In most cases, you would want to fire this trigger last for each row. Bearing in mind that triggers fire in name order, you would then @@ -20846,7 +20846,7 @@ Processing Objects Dropped by a DDL Command $$; CREATE EVENT TRIGGER test_event_trigger_for_drops ON sql_drop - EXECUTE PROCEDURE test_event_trigger_for_drops(); + EXECUTE FUNCTION test_event_trigger_for_drops(); @@ -20911,7 +20911,7 @@ Table Rewrite information CREATE EVENT TRIGGER test_table_rewrite_oid ON table_rewrite - EXECUTE PROCEDURE test_event_trigger_table_rewrite_oid(); + EXECUTE FUNCTION test_event_trigger_table_rewrite_oid(); diff --git a/doc/src/sgml/information_schema.sgml b/doc/src/sgml/information_schema.sgml index 09ef2827f2..9a61aa8541 100644 --- a/doc/src/sgml/information_schema.sgml +++ b/doc/src/sgml/information_schema.sgml @@ -5793,7 +5793,7 @@ <literal>triggers</literal> Columns character_data Statement that is executed by the trigger (currently always - EXECUTE PROCEDURE + EXECUTE FUNCTION function(...)) diff --git a/doc/src/sgml/lo.sgml b/doc/src/sgml/lo.sgml index ab8d192bc1..cce37932ec 100644 --- a/doc/src/sgml/lo.sgml +++ b/doc/src/sgml/lo.sgml @@ -70,7 +70,7 @@ How to Use It CREATE TABLE image (title text, raster lo); CREATE TRIGGER t_raster BEFORE UPDATE OR DELETE ON image - FOR EACH ROW EXECUTE PROCEDURE lo_manage(raster); + FOR EACH ROW EXECUTE FUNCTION lo_manage(raster); diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml index 6296a226b6..967efba3b5 100644 --- a/doc/src/sgml/plperl.sgml +++ b/doc/src/sgml/plperl.sgml @@ -1300,7 +1300,7 @@ PL/Perl Triggers CREATE TRIGGER test_valid_id_trig BEFORE INSERT OR UPDATE ON test - FOR EACH ROW EXECUTE PROCEDURE valid_id(); + FOR EACH ROW EXECUTE FUNCTION valid_id(); @@ -1350,7 +1350,7 @@ PL/Perl Event Triggers CREATE EVENT TRIGGER perl_a_snitch ON ddl_command_start - EXECUTE PROCEDURE perlsnitch(); + EXECUTE FUNCTION perlsnitch(); diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index abe67fa50e..6b19f18dd8 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -4069,7 +4069,7 @@ A <application>PL/pgSQL</application> Trigger Function $emp_stamp$ LANGUAGE plpgsql; CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp - FOR EACH ROW EXECUTE PROCEDURE emp_stamp(); + FOR EACH ROW EXECUTE FUNCTION emp_stamp(); @@ -4124,7 +4124,7 @@ A <application>PL/pgSQL</application> Trigger Function For Auditing</titl CREATE TRIGGER emp_audit AFTER INSERT OR UPDATE OR DELETE ON emp - FOR EACH ROW EXECUTE PROCEDURE process_emp_audit(); + FOR EACH ROW EXECUTE FUNCTION process_emp_audit(); </programlisting> </example> @@ -4203,7 +4203,7 @@ <title>A <application>PL/pgSQL</application> View Trigger Function For Auditing< CREATE TRIGGER emp_audit INSTEAD OF INSERT OR UPDATE OR DELETE ON emp_view - FOR EACH ROW EXECUTE PROCEDURE update_emp_view(); + FOR EACH ROW EXECUTE FUNCTION update_emp_view(); </programlisting> </example> @@ -4348,7 +4348,7 @@ <title>A <application>PL/pgSQL</application> Trigger Function For Maintaining A CREATE TRIGGER maint_sales_summary_bytime AFTER INSERT OR UPDATE OR DELETE ON sales_fact - FOR EACH ROW EXECUTE PROCEDURE maint_sales_summary_bytime(); + FOR EACH ROW EXECUTE FUNCTION maint_sales_summary_bytime(); INSERT INTO sales_fact VALUES(1,1,1,10,3,15); INSERT INTO sales_fact VALUES(1,2,1,20,5,35); @@ -4425,15 +4425,15 @@ <title>Auditing with Transition Tables CREATE TRIGGER emp_audit_ins AFTER INSERT ON emp REFERENCING NEW TABLE AS new_table - FOR EACH STATEMENT EXECUTE PROCEDURE process_emp_audit(); + FOR EACH STATEMENT EXECUTE FUNCTION process_emp_audit(); CREATE TRIGGER emp_audit_upd AFTER UPDATE ON emp REFERENCING OLD TABLE AS old_table NEW TABLE AS new_table - FOR EACH STATEMENT EXECUTE PROCEDURE process_emp_audit(); + FOR EACH STATEMENT EXECUTE FUNCTION process_emp_audit(); CREATE TRIGGER emp_audit_del AFTER DELETE ON emp REFERENCING OLD TABLE AS old_table - FOR EACH STATEMENT EXECUTE PROCEDURE process_emp_audit(); + FOR EACH STATEMENT EXECUTE FUNCTION process_emp_audit(); @@ -4498,7 +4498,7 @@ A <application>PL/pgSQL</application> Event Trigger Function END; $$ LANGUAGE plpgsql; -CREATE EVENT TRIGGER snitch ON ddl_command_start EXECUTE PROCEDURE snitch(); +CREATE EVENT TRIGGER snitch ON ddl_command_start EXECUTE FUNCTION snitch(); diff --git a/doc/src/sgml/pltcl.sgml b/doc/src/sgml/pltcl.sgml index 97906a67df..61c059a224 100644 --- a/doc/src/sgml/pltcl.sgml +++ b/doc/src/sgml/pltcl.sgml @@ -789,7 +789,7 @@ Trigger Functions in PL/Tcl CREATE TABLE mytab (num integer, description text, modcnt integer); CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab - FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt'); + FOR EACH ROW EXECUTE FUNCTION trigfunc_modcount('modcnt'); Notice that the trigger function itself does not know the column @@ -852,7 +852,7 @@ Event Trigger Functions in PL/Tcl elog NOTICE "tclsnitch: $TG_event $TG_tag" $$ LANGUAGE pltcl; -CREATE EVENT TRIGGER tcl_a_snitch ON ddl_command_start EXECUTE PROCEDURE tclsnitch(); +CREATE EVENT TRIGGER tcl_a_snitch ON ddl_command_start EXECUTE FUNCTION tclsnitch(); diff --git a/doc/src/sgml/ref/create_event_trigger.sgml b/doc/src/sgml/ref/create_event_trigger.sgml index 396d82118e..52ba746166 100644 --- a/doc/src/sgml/ref/create_event_trigger.sgml +++ b/doc/src/sgml/ref/create_event_trigger.sgml @@ -24,7 +24,7 @@ CREATE EVENT TRIGGER name ON event [ WHEN filter_variable IN (filter_value [, ... ]) [ AND ... ] ] - EXECUTE PROCEDURE function_name() + EXECUTE { FUNCTION | PROCEDURE } function_name() @@ -98,6 +98,14 @@ Parameters A user-supplied function that is declared as taking no argument and returning type event_trigger. + + + In the syntax of CREATE EVENT TRIGGER, the keywords + FUNCTION and PROCEDURE are + equivalent, but the referenced function must in any case be a function, + not a procedure. The use of the keyword PROCEDURE + here is historical and deprecated. + @@ -136,7 +144,7 @@ Examples $$; CREATE EVENT TRIGGER abort_ddl ON ddl_command_start - EXECUTE PROCEDURE abort_any_command(); + EXECUTE FUNCTION abort_any_command(); diff --git a/doc/src/sgml/ref/create_trigger.sgml b/doc/src/sgml/ref/create_trigger.sgml index b2dddafb46..6514ffc6ae 100644 --- a/doc/src/sgml/ref/create_trigger.sgml +++ b/doc/src/sgml/ref/create_trigger.sgml @@ -33,7 +33,7 @@ [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ] [ FOR [ EACH ] { ROW | STATEMENT } ] [ WHEN ( condition ) ] - EXECUTE PROCEDURE function_name ( arguments ) + EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments ) where event can be one of: @@ -401,6 +401,14 @@ Parameters and returning type trigger, which is executed when the trigger fires. + + + In the syntax of CREATE TRIGGER, the keywords + FUNCTION and PROCEDURE are + equivalent, but the referenced function must in any case be a function, + not a procedure. The use of the keyword PROCEDURE + here is historical and deprecated. + @@ -555,7 +563,7 @@ Examples CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW - EXECUTE PROCEDURE check_account_update(); + EXECUTE FUNCTION check_account_update(); The same, but only execute the function if column balance @@ -565,7 +573,7 @@ Examples CREATE TRIGGER check_update BEFORE UPDATE OF balance ON accounts FOR EACH ROW - EXECUTE PROCEDURE check_account_update(); + EXECUTE FUNCTION check_account_update(); This form only executes the function if column balance @@ -576,7 +584,7 @@ Examples BEFORE UPDATE ON accounts FOR EACH ROW WHEN (OLD.balance IS DISTINCT FROM NEW.balance) - EXECUTE PROCEDURE check_account_update(); + EXECUTE FUNCTION check_account_update(); Call a function to log updates of accounts, but only if @@ -587,7 +595,7 @@ Examples AFTER UPDATE ON accounts FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) - EXECUTE PROCEDURE log_account_update(); + EXECUTE FUNCTION log_account_update(); Execute the function view_insert_row for each row to insert @@ -597,7 +605,7 @@ Examples CREATE TRIGGER view_insert INSTEAD OF INSERT ON my_view FOR EACH ROW - EXECUTE PROCEDURE view_insert_row(); + EXECUTE FUNCTION view_insert_row(); Execute the function check_transfer_balances_to_zero for each @@ -609,7 +617,7 @@ Examples AFTER INSERT ON transfer REFERENCING NEW TABLE AS inserted FOR EACH STATEMENT - EXECUTE PROCEDURE check_transfer_balances_to_zero(); + EXECUTE FUNCTION check_transfer_balances_to_zero(); Execute the function check_matching_pairs for each row to @@ -621,7 +629,7 @@ Examples AFTER UPDATE ON paired_items REFERENCING NEW TABLE AS newtab OLD TABLE AS oldtab FOR EACH ROW - EXECUTE PROCEDURE check_matching_pairs(); + EXECUTE FUNCTION check_matching_pairs(); diff --git a/doc/src/sgml/tcn.sgml b/doc/src/sgml/tcn.sgml index 8cc55efd29..aa2fe4f00a 100644 --- a/doc/src/sgml/tcn.sgml +++ b/doc/src/sgml/tcn.sgml @@ -47,7 +47,7 @@ tcn CREATE TABLE test=# create trigger tcndata_tcn_trigger test-# after insert or update or delete on tcndata -test-# for each row execute procedure triggered_change_notification(); +test-# for each row execute function triggered_change_notification(); CREATE TRIGGER test=# listen tcn; LISTEN diff --git a/doc/src/sgml/textsearch.sgml b/doc/src/sgml/textsearch.sgml index 6df424c63e..800a94bb54 100644 --- a/doc/src/sgml/textsearch.sgml +++ b/doc/src/sgml/textsearch.sgml @@ -1884,7 +1884,7 @@ Triggers for Automatic Updates ); CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE -ON messages FOR EACH ROW EXECUTE PROCEDURE +ON messages FOR EACH ROW EXECUTE FUNCTION tsvector_update_trigger(tsv, 'pg_catalog.english', title, body); INSERT INTO messages VALUES('title here', 'the body text is here'); @@ -1940,7 +1940,7 @@ Triggers for Automatic Updates $$ LANGUAGE plpgsql; CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE - ON messages FOR EACH ROW EXECUTE PROCEDURE messages_trigger(); + ON messages FOR EACH ROW EXECUTE FUNCTION messages_trigger(); diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml index c43dbc9786..be9c228448 100644 --- a/doc/src/sgml/trigger.sgml +++ b/doc/src/sgml/trigger.sgml @@ -871,10 +871,10 @@ A Complete Trigger Example LANGUAGE C; CREATE TRIGGER tbefore BEFORE INSERT OR UPDATE OR DELETE ON ttest - FOR EACH ROW EXECUTE PROCEDURE trigf(); + FOR EACH ROW EXECUTE FUNCTION trigf(); CREATE TRIGGER tafter AFTER INSERT OR UPDATE OR DELETE ON ttest - FOR EACH ROW EXECUTE PROCEDURE trigf(); + FOR EACH ROW EXECUTE FUNCTION trigf(); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 90dfac2cb1..cda6895153 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -5344,7 +5344,7 @@ CreateAmStmt: CREATE ACCESS METHOD name TYPE_P INDEX HANDLER handler_name CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON qualified_name TriggerReferencing TriggerForSpec TriggerWhen - EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')' + EXECUTE FUNCTION_or_PROCEDURE func_name '(' TriggerFuncArgs ')' { CreateTrigStmt *n = makeNode(CreateTrigStmt); n->trigname = $3; @@ -5366,7 +5366,7 @@ CreateTrigStmt: | CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON qualified_name OptConstrFromTable ConstraintAttributeSpec FOR EACH ROW TriggerWhen - EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')' + EXECUTE FUNCTION_or_PROCEDURE func_name '(' TriggerFuncArgs ')' { CreateTrigStmt *n = makeNode(CreateTrigStmt); n->trigname = $4; @@ -5504,6 +5504,11 @@ TriggerWhen: | /*EMPTY*/ { $$ = NULL; } ; +FUNCTION_or_PROCEDURE: + FUNCTION + | PROCEDURE + ; + TriggerFuncArgs: TriggerFuncArg { $$ = list_make1($1); } | TriggerFuncArgs ',' TriggerFuncArg { $$ = lappend($1, $3); } diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index bf271d536e..843c94094b 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -22,12 +22,12 @@ create unique index pkeys_i on pkeys (pkey1, pkey2); create trigger check_fkeys_pkey_exist before insert or update on fkeys for each row - execute procedure + execute function check_primary_key ('fkey1', 'fkey2', 'pkeys', 'pkey1', 'pkey2'); create trigger check_fkeys_pkey2_exist before insert or update on fkeys for each row - execute procedure check_primary_key ('fkey3', 'fkeys2', 'pkey23'); + execute function check_primary_key ('fkey3', 'fkeys2', 'pkey23'); -- -- For fkeys2: -- (fkey21, fkey22) --> pkeys (pkey1, pkey2) diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index 7cfa5fdf92..451527dbd5 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -26,13 +26,13 @@ create trigger check_fkeys_pkey_exist before insert or update on fkeys for each row - execute procedure + execute function check_primary_key ('fkey1', 'fkey2', 'pkeys', 'pkey1', 'pkey2'); create trigger check_fkeys_pkey2_exist before insert or update on fkeys for each row - execute procedure check_primary_key ('fkey3', 'fkeys2', 'pkey23'); + execute function check_primary_key ('fkey3', 'fkeys2', 'pkey23'); -- -- For fkeys2: -- 2.18.0