Dear patchers,

Please find attached a small patch to add an optionnal "ALSO" keyword
to the "CREATE RULE" syntax.

The "ALSO" keyword can be used where "INSTEAD" would be used,
to mean the opposite, i.e. the current default behavior of rules
which adds operations to the current one. IMHO, it makes the
intended behavior much clearer for the basic user (say, me;-).

CREATE RULE some_table_del AS
  ON DELETE TO some_table DO ALSO
  (
    DELETE FROM this_other_table WHERE id=old.id;
  );

Of course, the absence of the "ALSO" keyword preserves the previous
behavior... that is it behaves the same as with the "ALSO" keyword.

This patch was made against 7.4.1 with the "difforig" script
provided by postgresql.

It adds "ALSO" keyword in the parser code (two lines), fixes somehow the
documentation and sql help, and modifies four of the "RULE"
test cases to use this keyword instead of the default nothing-ness.

It validated for me with a "make check".

Have a nice day,

-- 
Fabien Coelho - [EMAIL PROTECTED]
*** ./doc/src/sgml/rules.sgml.orig      Sun Feb 29 17:35:15 2004
--- ./doc/src/sgml/rules.sgml   Sun Feb 29 17:38:45 2004
***************
*** 873,879 ****
  
          <ListItem>
        <Para>
!           They can be <literal>INSTEAD</> or not.
        </Para>
        </ListItem>
  
--- 873,879 ----
  
          <ListItem>
        <Para>
!           They can be <literal>INSTEAD</> or <literal>ALSO</> (default).
        </Para>
        </ListItem>
  
***************
*** 904,910 ****
  <ProgramListing>
  CREATE RULE <replaceable>rule_name</> AS ON <replaceable>event</>
      TO <replaceable>object</> [WHERE <replaceable>rule_qualification</>]
!     DO [INSTEAD] [<replaceable>action</> | (<replaceable>actions</>) | NOTHING];
  </ProgramListing>
  
      in mind.
--- 904,910 ----
  <ProgramListing>
  CREATE RULE <replaceable>rule_name</> AS ON <replaceable>event</>
      TO <replaceable>object</> [WHERE <replaceable>rule_qualification</>]
!     DO [ALSO|INSTEAD] [<replaceable>action</> | (<replaceable>actions</>) | NOTHING];
  </ProgramListing>
  
      in mind.
***************
*** 920,926 ****
      Initially the query-tree list is empty.
      There can be zero (<literal>NOTHING</> key word), one, or multiple actions.
      To simplify, we will look at a rule with one action. This rule
!     can have a qualification or not and it can be <literal>INSTEAD</> or not.
  </Para>
  
  <Para>
--- 920,926 ----
      Initially the query-tree list is empty.
      There can be zero (<literal>NOTHING</> key word), one, or multiple actions.
      To simplify, we will look at a rule with one action. This rule
!     can have a qualification or not and it can be <literal>INSTEAD</> or 
<literal>ALSO</> (default).
  </Para>
  
  <Para>
***************
*** 937,943 ****
  
      <variablelist>
       <varlistentry>
!       <term>No qualification and not <literal>INSTEAD</></term>
        <listitem>
         <para>
          the query tree from the rule action with the original query
--- 937,943 ----
  
      <variablelist>
       <varlistentry>
!       <term>No qualification and <literal>ALSO</></term>
        <listitem>
         <para>
          the query tree from the rule action with the original query
***************
*** 957,963 ****
       </varlistentry>
  
       <varlistentry>
!       <term>Qualification given and not <literal>INSTEAD</></term>
        <listitem>
         <para>
          the query tree from the rule action with the rule
--- 957,963 ----
       </varlistentry>
  
       <varlistentry>
!       <term>Qualification given and <literal>ALSO</></term>
        <listitem>
         <para>
          the query tree from the rule action with the rule
***************
*** 980,986 ****
       </varlistentry>
      </variablelist>
  
!     Finally, if the rule is not <literal>INSTEAD</>, the unchanged original query 
tree is
      added to the list. Since only qualified <literal>INSTEAD</> rules already add the
      original query tree, we end up with either one or two output query trees
      for a rule with one action.
--- 980,986 ----
       </varlistentry>
      </variablelist>
  
!     Finally, if the rule is <literal>ALSO</>, the unchanged original query tree is
      added to the list. Since only qualified <literal>INSTEAD</> rules already add the
      original query tree, we end up with either one or two output query trees
      for a rule with one action.
***************
*** 1111,1117 ****
  </Para>
  
  <Para>
!     The rule is a qualified non-<literal>INSTEAD</> rule, so the rule system
      has to return two query trees: the modified rule action and the original
      query tree. In step 1, the range table of the original query is
      incorporated into the rule's action query tree. This results in:
--- 1111,1117 ----
  </Para>
  
  <Para>
!     The rule is a qualified <literal>ALSO</> rule, so the rule system
      has to return two query trees: the modified rule action and the original
      query tree. In step 1, the range table of the original query is
      incorporated into the rule's action query tree. This results in:
***************
*** 1190,1196 ****
     </para>
  
     <para>
!     That's it.  Since the rule is not <literal>INSTEAD</>, we also output the
      original query tree.  In short, the output from the rule system
      is a list of two query trees that correspond to these statements:
  
--- 1190,1196 ----
     </para>
  
     <para>
!     That's it.  Since the rule is <literal>ALSO</>, we also output the
      original query tree.  In short, the output from the rule system
      is a list of two query trees that correspond to these statements:
  
*** ./src/backend/parser/gram.y.orig    Sun Feb 29 17:32:48 2004
--- ./src/backend/parser/gram.y Sun Feb 29 17:33:21 2004
***************
*** 327,333 ****
  
  /* ordinary key words in alphabetical order */
  %token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD AFTER
!       AGGREGATE ALL ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC
        ASSERTION ASSIGNMENT AT AUTHORIZATION
  
        BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
--- 327,333 ----
  
  /* ordinary key words in alphabetical order */
  %token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD AFTER
!       AGGREGATE ALL ALSO ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC
        ASSERTION ASSIGNMENT AT AUTHORIZATION
  
        BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
***************
*** 3529,3534 ****
--- 3529,3535 ----
  
  opt_instead:
                        INSTEAD                                                        
         { $$ = TRUE; }
+                       | ALSO                                                         
         { $$ = FALSE; }
                        | /*EMPTY*/                                                    
         { $$ = FALSE; }
                ;
  
*** ./src/backend/parser/keywords.c.orig        Sun Feb 29 17:29:44 2004
--- ./src/backend/parser/keywords.c     Sun Feb 29 17:30:27 2004
***************
*** 38,43 ****
--- 38,44 ----
        {"after", AFTER},
        {"aggregate", AGGREGATE},
        {"all", ALL},
+       {"also", ALSO},
        {"alter", ALTER},
        {"analyse", ANALYSE},           /* British spelling */
        {"analyze", ANALYZE},
*** ./src/bin/psql/sql_help.h.orig      Sun Feb 29 17:42:06 2004
--- ./src/bin/psql/sql_help.h   Sun Feb 29 17:42:20 2004
***************
*** 159,165 ****
  
      { "CREATE RULE",
        N_("define a new rewrite rule"),
!       N_("CREATE [ OR REPLACE ] RULE name AS ON event\n    TO table [ WHERE 
condition ]\n    DO [ INSTEAD ] { NOTHING | command | ( command ; command ... ) }") },
  
      { "CREATE SCHEMA",
        N_("define a new schema"),
--- 159,165 ----
  
      { "CREATE RULE",
        N_("define a new rewrite rule"),
!       N_("CREATE [ OR REPLACE ] RULE name AS ON event\n    TO table [ WHERE 
condition ]\n    DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) 
}") },
  
      { "CREATE SCHEMA",
        N_("define a new schema"),
*** ./src/test/regress/expected/rules.out.orig  Sun Feb 29 17:58:54 2004
--- ./src/test/regress/expected/rules.out       Sun Feb 29 17:59:10 2004
***************
*** 29,47 ****
  create table rtest_interface (sysname text, ifname text);
  create table rtest_person (pname text, pdesc text);
  create table rtest_admin (pname text, sysname text);
! create rule rtest_sys_upd as on update to rtest_system do (
        update rtest_interface set sysname = new.sysname 
                where sysname = old.sysname;
        update rtest_admin set sysname = new.sysname 
                where sysname = old.sysname
        );
! create rule rtest_sys_del as on delete to rtest_system do (
        delete from rtest_interface where sysname = old.sysname;
        delete from rtest_admin where sysname = old.sysname;
        );
! create rule rtest_pers_upd as on update to rtest_person do 
        update rtest_admin set pname = new.pname where pname = old.pname;
! create rule rtest_pers_del as on delete to rtest_person do 
        delete from rtest_admin where pname = old.pname;
  --
  -- Tables and rules for the logging test
--- 29,47 ----
  create table rtest_interface (sysname text, ifname text);
  create table rtest_person (pname text, pdesc text);
  create table rtest_admin (pname text, sysname text);
! create rule rtest_sys_upd as on update to rtest_system do also (
        update rtest_interface set sysname = new.sysname 
                where sysname = old.sysname;
        update rtest_admin set sysname = new.sysname 
                where sysname = old.sysname
        );
! create rule rtest_sys_del as on delete to rtest_system do also (
        delete from rtest_interface where sysname = old.sysname;
        delete from rtest_admin where sysname = old.sysname;
        );
! create rule rtest_pers_upd as on update to rtest_person do also
        update rtest_admin set pname = new.pname where pname = old.pname;
! create rule rtest_pers_del as on delete to rtest_person do also
        delete from rtest_admin where pname = old.pname;
  --
  -- Tables and rules for the logging test
*** ./src/test/regress/sql/rules.sql.orig       Sun Feb 29 17:43:59 2004
--- ./src/test/regress/sql/rules.sql    Sun Feb 29 17:45:47 2004
***************
*** 33,54 ****
  create table rtest_person (pname text, pdesc text);
  create table rtest_admin (pname text, sysname text);
  
! create rule rtest_sys_upd as on update to rtest_system do (
        update rtest_interface set sysname = new.sysname 
                where sysname = old.sysname;
        update rtest_admin set sysname = new.sysname 
                where sysname = old.sysname
        );
  
! create rule rtest_sys_del as on delete to rtest_system do (
        delete from rtest_interface where sysname = old.sysname;
        delete from rtest_admin where sysname = old.sysname;
        );
  
! create rule rtest_pers_upd as on update to rtest_person do 
        update rtest_admin set pname = new.pname where pname = old.pname;
  
! create rule rtest_pers_del as on delete to rtest_person do 
        delete from rtest_admin where pname = old.pname;
  
  --
--- 33,54 ----
  create table rtest_person (pname text, pdesc text);
  create table rtest_admin (pname text, sysname text);
  
! create rule rtest_sys_upd as on update to rtest_system do also (
        update rtest_interface set sysname = new.sysname 
                where sysname = old.sysname;
        update rtest_admin set sysname = new.sysname 
                where sysname = old.sysname
        );
  
! create rule rtest_sys_del as on delete to rtest_system do also (
        delete from rtest_interface where sysname = old.sysname;
        delete from rtest_admin where sysname = old.sysname;
        );
  
! create rule rtest_pers_upd as on update to rtest_person do also
        update rtest_admin set pname = new.pname where pname = old.pname;
  
! create rule rtest_pers_del as on delete to rtest_person do also
        delete from rtest_admin where pname = old.pname;
  
  --
*** ./doc/src/sgml/keywords.sgml.orig   Sun Feb 29 18:44:44 2004
--- ./doc/src/sgml/keywords.sgml        Sun Feb 29 18:45:40 2004
***************
*** 171,176 ****
--- 171,182 ----
      <entry>reserved</entry>
     </row>
     <row>
+     <entry><token>ALSO</token></entry>
+     <entry>non-reserved</entry>
+     <entry></entry>
+     <entry></entry>
+    </row>
+    <row>
      <entry><token>ALTER</token></entry>
      <entry>non-reserved</entry>
      <entry>reserved</entry>
---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend

Reply via email to