]> granicus.if.org Git - postgresql/commitdiff
Rule names are now unique per-relation, rather than unique globally.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 18 Apr 2002 20:01:11 +0000 (20:01 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 18 Apr 2002 20:01:11 +0000 (20:01 +0000)
DROP RULE and COMMENT ON RULE syntax adds an 'ON tablename' clause,
similar to TRIGGER syntaxes.  To allow loading of existing pg_dump
files containing COMMENT ON RULE, the COMMENT code will still accept
the old syntax --- but only if the target rulename is unique across
the whole database.

35 files changed:
doc/src/sgml/func.sgml
doc/src/sgml/ref/comment.sgml
doc/src/sgml/ref/drop_rule.sgml
doc/src/sgml/release.sgml
src/backend/catalog/indexing.c
src/backend/commands/comment.c
src/backend/commands/tablecmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/rewrite/rewriteDefine.c
src/backend/rewrite/rewriteRemove.c
src/backend/rewrite/rewriteSupport.c
src/backend/tcop/postgres.c
src/backend/tcop/utility.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/cache/relcache.c
src/backend/utils/cache/syscache.c
src/bin/initdb/initdb.sh
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_rewrite.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/include/rewrite/rewriteDefine.h
src/include/rewrite/rewriteRemove.h
src/include/rewrite/rewriteSupport.h
src/include/utils/builtins.h
src/include/utils/syscache.h
src/test/regress/expected/errors.out
src/test/regress/expected/rules.out
src/test/regress/sql/errors.sql
src/test/regress/sql/rules.sql

index c62394e9145ae03e56321b2b4c0b8141a07400f3..3ada43a7983b6e24db2bba7c8314a64672e16360 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.94 2002/03/22 19:20:09 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.95 2002/04/18 20:01:08 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -4344,7 +4344,12 @@ SELECT NULLIF(value, '(none)') ...
        <entry>Get CREATE VIEW command for view</>
       </row>
       <row>
-       <entry><function>pg_get_ruledef</>(<parameter>rulename</parameter>)</entry>
+       <entry><function>pg_get_viewdef</>(<parameter>viewOID</parameter>)</entry>
+       <entry><type>text</></entry>
+       <entry>Get CREATE VIEW command for view</>
+      </row>
+      <row>
+       <entry><function>pg_get_ruledef</>(<parameter>ruleOID</parameter>)</entry>
        <entry><type>text</></entry>
        <entry>Get CREATE RULE command for rule</>
       </row>
index f3530b71ce6cd80ab6c65ae55eb8695ff41d28f6..c07c36e82de27f5129bccafd55c317ba78ff6d9d 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.15 2002/03/19 02:18:12 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.16 2002/04/18 20:01:09 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -25,11 +25,12 @@ PostgreSQL documentation
   <synopsis>
 COMMENT ON
 [
-  [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
+  [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
   COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
   AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
   FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
   OPERATOR <replaceable class="PARAMETER">op</replaceable> (<replaceable class="PARAMETER">leftoperand_type</replaceable> <replaceable class="PARAMETER">rightoperand_type</replaceable>) |
+  RULE <replaceable class="PARAMETER">rule_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> |
   TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
 ] IS <replaceable class="PARAMETER">'text'</replaceable>
   </synopsis>
@@ -46,7 +47,7 @@ COMMENT ON
     <variablelist>
      <varlistentry>
       <term><replaceable class="PARAMETER">object_name, table_name,
-      column_name, agg_name, func_name, op, trigger_name</replaceable></term>
+      column_name, agg_name, func_name, op, rule_name, trigger_name</replaceable></term>
       <listitem>
        <para>
        The name of the object to be be commented.
@@ -143,7 +144,6 @@ COMMENT ON mytable IS 'This is my table.';
 COMMENT ON DATABASE my_database IS 'Development Database';
 COMMENT ON DOMAIN my_domain IS 'Email Address Domain';
 COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee id';
-COMMENT ON RULE my_rule IS 'Logs UPDATES of employee records';
 COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
 COMMENT ON TABLE my_table IS 'Employee Information';
 COMMENT ON TYPE my_type IS 'Complex Number support';
@@ -152,6 +152,7 @@ COMMENT ON COLUMN my_table.my_field IS 'Employee ID number';
 COMMENT ON AGGREGATE my_aggregate (double precision) IS 'Computes sample variance';
 COMMENT ON FUNCTION my_function (timestamp) IS 'Returns Roman Numeral';
 COMMENT ON OPERATOR ^ (text, text) IS 'Performs intersection of two text';
+COMMENT ON RULE my_rule ON my_table IS 'Logs UPDATES of employee records';
 COMMENT ON TRIGGER my_trigger ON my_table IS 'Used for R.I.';
    </programlisting>
   </para>
index 452ff48a18dbdabc8a31a6a3a6a5646d6655683a..522c81a62823edb76af9f77fc28276cce46fcd1e 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_rule.sgml,v 1.11 2001/12/08 03:24:36 thomas Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_rule.sgml,v 1.12 2002/04/18 20:01:09 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -23,7 +23,7 @@ PostgreSQL documentation
    <date>1998-09-22</date>
   </refsynopsisdivinfo>
   <synopsis>
-DROP RULE <replaceable class="PARAMETER">name</replaceable> [, ...]
+DROP RULE <replaceable class="PARAMETER">name</replaceable> ON <replaceable class="PARAMETER">relation</replaceable>
   </synopsis>
   
   <refsect2 id="R2-SQL-DROPRULE-1">
@@ -43,6 +43,14 @@ DROP RULE <replaceable class="PARAMETER">name</replaceable> [, ...]
        </para>
       </listitem>
      </varlistentry>
+     <varlistentry>
+      <term><replaceable class="parameter">relation</replaceable></term>
+      <listitem>
+       <para>
+       The name of the relation the rule applies to.
+       </para>
+      </listitem>
+     </varlistentry>
     </variablelist>
    </para>
   </refsect2>
@@ -68,7 +76,7 @@ DROP
      </varlistentry>
      <varlistentry>
       <term><computeroutput>
-ERROR:  Rule or view "<replaceable class="parameter">name</replaceable>" not found
+ERROR:  Rule "<replaceable class="parameter">name</replaceable>" not found
        </computeroutput></term>
       <listitem>
        <para>
@@ -113,11 +121,6 @@ ERROR:  Rule or view "<replaceable class="parameter">name</replaceable>" not fou
     Refer to <command>CREATE RULE</command> for
     information on how to create rules.
    </para>
-
-   <para>
-    Once a rule is dropped, access to historical information
-    the rule has written may disappear.
-   </para>
   </refsect2>
  </refsect1>
   
@@ -129,7 +132,7 @@ ERROR:  Rule or view "<replaceable class="parameter">name</replaceable>" not fou
    To drop the rewrite rule <literal>newrule</literal>:
 
    <programlisting>
-DROP RULE newrule;
+DROP RULE newrule ON mytable;
    </programlisting>
   </para>
  </refsect1>
index a2ace11be545038eaf0f5016bf3528ef062dd802..0fe78be9943427336472ce761fe0b25db9a6eeff 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.132 2002/04/10 22:46:48 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.133 2002/04/18 20:01:08 tgl Exp $
 -->
 
 <appendix id="release">
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
 worries about funny characters.
 -->
 <literallayout><![CDATA[
+Rule names are now per-relation, not global; DROP RULE and COMMENT ON RULE syntax changes accordingly
 Readline and Zlib are now required by default and must be turned off explicitly if their use is not desired
 Define a third class of function volatility to allow indexscans in more cases
 Locale support is now built by default; choice of locale is set by initdb and/or at run-time
index 203df67f628edf35dae10d0fa8157dd983a83a83..6ccb1ef0b2b0e72b86f22c757ba88b245bdda596 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.90 2002/04/17 20:57:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.91 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -68,7 +68,7 @@ char     *Name_pg_proc_indices[Num_pg_proc_indices] =
 char      *Name_pg_relcheck_indices[Num_pg_relcheck_indices] =
 {RelCheckIndex};
 char      *Name_pg_rewrite_indices[Num_pg_rewrite_indices] =
-{RewriteOidIndex, RewriteRulenameIndex};
+{RewriteOidIndex, RewriteRelRulenameIndex};
 char      *Name_pg_shadow_indices[Num_pg_shadow_indices] =
 {ShadowNameIndex, ShadowSysidIndex};
 char      *Name_pg_statistic_indices[Num_pg_statistic_indices] =
index 3eb9a5eb67afd77b0f273c72a76135affd670626..07b14ca4fe214bac9fbd328c2c76f6d6684f905f 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.41 2002/04/16 23:08:10 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.42 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -472,44 +472,105 @@ CommentDatabase(List *qualname, char *comment)
  * CommentRule --
  *
  * This routine is used to add/drop any user-comments a user might
- * have regarding a specified RULE. The rule is specified by name
- * and, if found, and the user has appropriate permissions, a
- * comment will be added/dropped using the CreateComments() routine.
+ * have regarding a specified RULE. The rule for commenting is determined by
+ * both its name and the relation to which it refers. The arguments to this
+ * function are the rule name and relation name (merged into a qualified
+ * name), and the comment to add/drop.
+ *
+ * Before PG 7.3, rules had unique names across the whole database, and so
+ * the syntax was just COMMENT ON RULE rulename, with no relation name.
+ * For purposes of backwards compatibility, we support that as long as there
+ * is only one rule by the specified name in the database.
  */
 static void
 CommentRule(List *qualname, char *comment)
 {
-       char       *rule;
+       int                     nnames;
+       List       *relname;
+       char       *rulename;
+       RangeVar   *rel;
+       Relation        relation;
        HeapTuple       tuple;
        Oid                     reloid;
        Oid                     ruleoid;
        Oid                     classoid;
        int32           aclcheck;
 
-       /* XXX this is gonna change soon */
-       if (length(qualname) != 1)
-               elog(ERROR, "CommentRule: rule name may not be qualified");
-       rule = strVal(lfirst(qualname));
-
-       /* Find the rule's pg_rewrite tuple, get its OID and its table's OID */
+       /* Separate relname and trig name */
+       nnames = length(qualname);
+       if (nnames == 1)
+       {
+               /* Old-style: only a rule name is given */
+               Relation        RewriteRelation;
+               HeapScanDesc scanDesc;
+               ScanKeyData scanKeyData;
+
+               rulename = strVal(lfirst(qualname));
+
+               /* Search pg_rewrite for such a rule */
+               ScanKeyEntryInitialize(&scanKeyData,
+                                                          0,
+                                                          Anum_pg_rewrite_rulename,
+                                                          F_NAMEEQ,
+                                                          PointerGetDatum(rulename));
+
+               RewriteRelation = heap_openr(RewriteRelationName, AccessShareLock);
+               scanDesc = heap_beginscan(RewriteRelation,
+                                                                 0, SnapshotNow, 1, &scanKeyData);
+
+               tuple = heap_getnext(scanDesc, 0);
+               if (HeapTupleIsValid(tuple))
+               {
+                       reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
+                       ruleoid = tuple->t_data->t_oid;
+               }
+               else
+               {
+                       elog(ERROR, "rule '%s' does not exist", rulename);
+                       reloid = ruleoid = 0; /* keep compiler quiet */
+               }
 
-       tuple = SearchSysCache(RULENAME,
-                                                  PointerGetDatum(rule),
-                                                  0, 0, 0);
-       if (!HeapTupleIsValid(tuple))
-               elog(ERROR, "rule '%s' does not exist", rule);
+               if (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
+                       elog(ERROR, "There are multiple rules '%s'"
+                                "\n\tPlease specify a relation name as well as a rule name",
+                                rulename);
 
-       reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
-       ruleoid = tuple->t_data->t_oid;
+               heap_endscan(scanDesc);
+               heap_close(RewriteRelation, AccessShareLock);
 
-       ReleaseSysCache(tuple);
+               /* Open the owning relation to ensure it won't go away meanwhile */
+               relation = heap_open(reloid, AccessShareLock);
+       }
+       else
+       {
+               /* New-style: rule and relname both provided */
+               Assert(nnames >= 2);
+               relname = ltruncate(nnames-1, listCopy(qualname));
+               rulename = strVal(nth(nnames-1, qualname));
+
+               /* Open the owning relation to ensure it won't go away meanwhile */
+               rel = makeRangeVarFromNameList(relname);
+               relation = heap_openrv(rel, AccessShareLock);
+               reloid = RelationGetRelid(relation);
+
+               /* Find the rule's pg_rewrite tuple, get its OID */
+               tuple = SearchSysCache(RULERELNAME,
+                                                          ObjectIdGetDatum(reloid),
+                                                          PointerGetDatum(rulename),
+                                                          0, 0);
+               if (!HeapTupleIsValid(tuple))
+                       elog(ERROR, "rule '%s' does not exist", rulename);
+               Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
+               ruleoid = tuple->t_data->t_oid;
+               ReleaseSysCache(tuple);
+       }
 
        /* Check object security */
 
        aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE);
        if (aclcheck != ACLCHECK_OK)
                elog(ERROR, "you are not permitted to comment on rule '%s'",
-                        rule);
+                        rulename);
 
        /* pg_rewrite doesn't have a hard-coded OID, so must look it up */
 
index f6c9b48c09725eb5b29885ad86d802ad0afb50b1..8abd8cf80deb39c0c7e553d5f5a937e9ec30dd41 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.2 2002/04/15 23:45:07 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.3 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1423,8 +1423,8 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
        Relation        ridescs[Num_pg_class_indices];
        Oid                     toast_relid;
        Oid                     toast_idxid;
-       char            toast_relname[NAMEDATALEN + 1];
-       char            toast_idxname[NAMEDATALEN + 1];
+       char            toast_relname[NAMEDATALEN];
+       char            toast_idxname[NAMEDATALEN];
        IndexInfo  *indexInfo;
        Oid                     classObjectId[2];
 
@@ -1667,7 +1667,7 @@ needs_toast_table(Relation rel)
 Oid
 DefineRelation(CreateStmt *stmt, char relkind)
 {
-       char       *relname = palloc(NAMEDATALEN);
+       char            relname[NAMEDATALEN];
        Oid                     namespaceId;
        List       *schema = stmt->tableElts;
        int                     numberOfAttributes;
@@ -1686,7 +1686,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
         * Truncate relname to appropriate length (probably a waste of time,
         * as parser should have done this already).
         */
-       StrNCpy(relname, (stmt->relation)->relname, NAMEDATALEN);
+       StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);
 
        /*
         * Look up the namespace in which we are supposed to create the
@@ -2642,8 +2642,8 @@ renameatt(Oid relid,
                                                         0, 0))
                elog(ERROR, "renameatt: attribute \"%s\" exists", newattname);
 
-       StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
-                       newattname, NAMEDATALEN);
+       namestrcpy(&(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
+                          newattname);
 
        simple_heap_update(attrelation, &atttup->t_self, atttup);
 
@@ -2699,8 +2699,8 @@ renameatt(Oid relid,
                /*
                 * Update the (copied) attribute tuple.
                 */
-               StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
-                               newattname, NAMEDATALEN);
+               namestrcpy(&(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
+                                  newattname);
 
                simple_heap_update(attrelation, &atttup->t_self, atttup);
 
@@ -2753,6 +2753,7 @@ renamerel(Oid relid, const char *newrelname)
        Relation        relrelation;    /* for RELATION relation */
        HeapTuple       reltup;
        Oid                     namespaceId;
+       char       *oldrelname;
        char            relkind;
        bool            relhastriggers;
        Relation        irelations[Num_pg_class_indices];
@@ -2763,13 +2764,14 @@ renamerel(Oid relid, const char *newrelname)
         */
        targetrelation = relation_open(relid, AccessExclusiveLock);
 
+       oldrelname = pstrdup(RelationGetRelationName(targetrelation));
        namespaceId = RelationGetNamespace(targetrelation);
 
        /* Validity checks */
        if (!allowSystemTableMods &&
                IsSystemRelation(targetrelation))
                elog(ERROR, "renamerel: system relation \"%s\" may not be renamed",
-                        RelationGetRelationName(targetrelation));
+                        oldrelname);
 
        relkind = targetrelation->rd_rel->relkind;
        relhastriggers = (targetrelation->rd_rel->reltriggers > 0);
@@ -2785,7 +2787,7 @@ renamerel(Oid relid, const char *newrelname)
                                                                0, 0, 0);
        if (!HeapTupleIsValid(reltup))
                elog(ERROR, "renamerel: relation \"%s\" does not exist",
-                        RelationGetRelationName(targetrelation));
+                        oldrelname);
 
        if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
                elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
@@ -2794,8 +2796,7 @@ renamerel(Oid relid, const char *newrelname)
         * Update pg_class tuple with new relname.      (Scribbling on reltup is
         * OK because it's a copy...)
         */
-       StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname),
-                       newrelname, NAMEDATALEN);
+       namestrcpy(&(((Form_pg_class) GETSTRUCT(reltup))->relname), newrelname);
 
        simple_heap_update(relrelation, &reltup->t_self, reltup);
 
@@ -2811,8 +2812,7 @@ renamerel(Oid relid, const char *newrelname)
         * Also rename the associated type, if any.
         */
        if (relkind != RELKIND_INDEX)
-               TypeRename(RelationGetRelationName(targetrelation), namespaceId,
-                                  newrelname);
+               TypeRename(oldrelname, namespaceId, newrelname);
 
        /*
         * If it's a view, must also rename the associated ON SELECT rule.
@@ -2822,9 +2822,9 @@ renamerel(Oid relid, const char *newrelname)
                char       *oldrulename,
                                   *newrulename;
 
-               oldrulename = MakeRetrieveViewRuleName(RelationGetRelationName(targetrelation));
+               oldrulename = MakeRetrieveViewRuleName(oldrelname);
                newrulename = MakeRetrieveViewRuleName(newrelname);
-               RenameRewriteRule(oldrulename, newrulename);
+               RenameRewriteRule(relid, oldrulename, newrulename);
        }
 
        /*
@@ -2834,12 +2834,12 @@ renamerel(Oid relid, const char *newrelname)
        {
                /* update tgargs where relname is primary key */
                update_ri_trigger_args(relid,
-                                                          RelationGetRelationName(targetrelation),
+                                                          oldrelname,
                                                           newrelname,
                                                           false, true);
                /* update tgargs where relname is foreign key */
                update_ri_trigger_args(relid,
-                                                          RelationGetRelationName(targetrelation),
+                                                          oldrelname,
                                                           newrelname,
                                                           true, true);
        }
index 8417f7a716c59afc3429e5839336e299fd53f138..d9d5d13d8d46ef89c4639ccf8efe11ae404c6bde 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.179 2002/04/17 20:57:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.180 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2380,14 +2380,15 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
        return newnode;
 }
 
-static DropTrigStmt *
-_copyDropTrigStmt(DropTrigStmt *from)
+static DropPropertyStmt *
+_copyDropPropertyStmt(DropPropertyStmt *from)
 {
-       DropTrigStmt *newnode = makeNode(DropTrigStmt);
+       DropPropertyStmt *newnode = makeNode(DropPropertyStmt);
 
-       if (from->trigname)
-               newnode->trigname = pstrdup(from->trigname);
        Node_Copy(from, newnode, relation);
+       if (from->property)
+               newnode->property = pstrdup(from->property);
+       newnode->removeType = from->removeType;
 
        return newnode;
 }
@@ -2915,8 +2916,8 @@ copyObject(void *from)
                case T_CreateTrigStmt:
                        retval = _copyCreateTrigStmt(from);
                        break;
-               case T_DropTrigStmt:
-                       retval = _copyDropTrigStmt(from);
+               case T_DropPropertyStmt:
+                       retval = _copyDropPropertyStmt(from);
                        break;
                case T_CreatePLangStmt:
                        retval = _copyCreatePLangStmt(from);
index 58f6b5a5d6353aa7c2cd6297053cbd5d352747f0..42030b272684e54c4628ae3ae41f0cb392f6b8a9 100644 (file)
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.127 2002/04/17 20:57:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.128 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1232,12 +1232,14 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
 }
 
 static bool
-_equalDropTrigStmt(DropTrigStmt *a, DropTrigStmt *b)
+_equalDropPropertyStmt(DropPropertyStmt *a, DropPropertyStmt *b)
 {
-       if (!equalstr(a->trigname, b->trigname))
-               return false;
        if (!equal(a->relation, b->relation))
                return false;
+       if (!equalstr(a->property, b->property))
+               return false;
+       if (a->removeType != b->removeType)
+               return false;
 
        return true;
 }
@@ -2080,8 +2082,8 @@ equal(void *a, void *b)
                case T_CreateTrigStmt:
                        retval = _equalCreateTrigStmt(a, b);
                        break;
-               case T_DropTrigStmt:
-                       retval = _equalDropTrigStmt(a, b);
+               case T_DropPropertyStmt:
+                       retval = _equalDropPropertyStmt(a, b);
                        break;
                case T_CreatePLangStmt:
                        retval = _equalCreatePLangStmt(a, b);
index 774f9fa743cbcbed648c72541d9da042805883c8..e4ec05abf2464961bb96294b51cbde7e72ee73b7 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.303 2002/04/17 20:57:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.304 2002/04/18 20:01:09 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -134,7 +134,7 @@ static bool set_name_needs_quotes(const char *name);
                CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
                CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
                DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
-               DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
+               DropRuleStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
                GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
                NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt,
                RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt,
@@ -469,6 +469,7 @@ stmt : AlterDatabaseSetStmt
                | DropGroupStmt
                | DropPLangStmt
                | DropTrigStmt
+               | DropRuleStmt
                | DropUserStmt
                | ExplainStmt
                | FetchStmt
@@ -2062,9 +2063,10 @@ ConstraintTimeSpec: INITIALLY IMMEDIATE
 
 DropTrigStmt:  DROP TRIGGER name ON qualified_name
                                {
-                                       DropTrigStmt *n = makeNode(DropTrigStmt);
-                                       n->trigname = $3;
+                                       DropPropertyStmt *n = makeNode(DropPropertyStmt);
                                        n->relation = $5;
+                                       n->property = $3;
+                                       n->removeType = DROP_TRIGGER;
                                        $$ = (Node *) n;
                                }
                ;
@@ -2154,7 +2156,6 @@ drop_type: TABLE                                                          { $$ = DROP_TABLE; }
                | SEQUENCE                                                              { $$ = DROP_SEQUENCE; }
                | VIEW                                                                  { $$ = DROP_VIEW; }
                | INDEX                                                                 { $$ = DROP_INDEX; }
-               | RULE                                                                  { $$ = DROP_RULE; }
                | TYPE_P                                                                { $$ = DROP_TYPE; }
                | DOMAIN_P                                                              { $$ = DROP_DOMAIN; }
                ;
@@ -2191,11 +2192,11 @@ TruncateStmt:  TRUNCATE opt_table qualified_name
  *  The COMMENT ON statement can take different forms based upon the type of
  *  the object associated with the comment. The form of the statement is:
  *
- *  COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] 
+ *  COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW ]
  *               <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION 
  *              <funcname> (arg1, arg2, ...) | OPERATOR <op> 
  *              (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
- *              <relname> ] IS 'text'
+ *              <relname> | RULE <rulename> ON <relname> ] IS 'text'
  *
  *****************************************************************************/
  
@@ -2244,12 +2245,30 @@ CommentStmt:    COMMENT ON comment_type any_name IS comment_text
                                n->comment = $8;
                                $$ = (Node *) n;
                        }
+               | COMMENT ON RULE name ON any_name IS comment_text
+                       {
+                               CommentStmt *n = makeNode(CommentStmt);
+                               n->objtype = RULE;
+                               n->objname = lappend($6, makeString($4));
+                               n->objargs = NIL;
+                               n->comment = $8;
+                               $$ = (Node *) n;
+                       }
+               | COMMENT ON RULE name IS comment_text
+                       {
+                               /* Obsolete syntax supported for awhile for compatibility */
+                               CommentStmt *n = makeNode(CommentStmt);
+                               n->objtype = RULE;
+                               n->objname = makeList1(makeString($4));
+                               n->objargs = NIL;
+                               n->comment = $6;
+                               $$ = (Node *) n;
+                       }
                ;
 
 comment_type:  COLUMN { $$ = COLUMN; }
                | DATABASE { $$ = DATABASE; }
                | INDEX { $$ = INDEX; }
-               | RULE { $$ = RULE; }
                | SEQUENCE { $$ = SEQUENCE; }
                | TABLE { $$ = TABLE; }
                | DOMAIN_P { $$ = TYPE_P; }
@@ -2977,6 +2996,17 @@ opt_instead:  INSTEAD                                    { $$ = TRUE; }
                ;
 
 
+DropRuleStmt:  DROP RULE name ON qualified_name
+                               {
+                                       DropPropertyStmt *n = makeNode(DropPropertyStmt);
+                                       n->relation = $5;
+                                       n->property = $3;
+                                       n->removeType = DROP_RULE;
+                                       $$ = (Node *) n;
+                               }
+               ;
+
+
 /*****************************************************************************
  *
  *             QUERY:
index f20c9a0d982d7de1de7fe4c5b8ce7b8a70f13901..8b40aeb4f735138a1003ff7318a2a8612f51eb70 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.66 2002/03/26 19:16:02 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.67 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,7 +37,7 @@ static bool setRuleCheckAsUser_walker(Node *node, Oid *context);
 
 /*
  * InsertRule -
- *       takes the arguments and inserts them as attributes into the system
+ *       takes the arguments and inserts them as a row into the system
  *       relation "pg_rewrite"
  */
 static Oid
@@ -58,7 +58,7 @@ InsertRule(char *rulname,
        HeapTuple       tup;
        Oid                     rewriteObjectId;
 
-       if (IsDefinedRewriteRule(rulname))
+       if (IsDefinedRewriteRule(eventrel_oid, rulname))
                elog(ERROR, "Attempt to insert rule \"%s\" failed: already exists",
                         rulname);
 
@@ -69,13 +69,13 @@ InsertRule(char *rulname,
 
        i = 0;
        namestrcpy(&rname, rulname);
-       values[i++] = NameGetDatum(&rname);
-       values[i++] = CharGetDatum(evtype + '0');
-       values[i++] = ObjectIdGetDatum(eventrel_oid);
-       values[i++] = Int16GetDatum(evslot_index);
-       values[i++] = BoolGetDatum(evinstead);
-       values[i++] = DirectFunctionCall1(textin, CStringGetDatum(evqual));
-       values[i++] = DirectFunctionCall1(textin, CStringGetDatum(actiontree));
+       values[i++] = NameGetDatum(&rname);                             /* rulename */
+       values[i++] = ObjectIdGetDatum(eventrel_oid);   /* ev_class */
+       values[i++] = Int16GetDatum(evslot_index);              /* ev_attr */
+       values[i++] = CharGetDatum(evtype + '0');               /* ev_type */
+       values[i++] = BoolGetDatum(evinstead);                  /* is_instead */
+       values[i++] = DirectFunctionCall1(textin, CStringGetDatum(evqual));     /* ev_qual */
+       values[i++] = DirectFunctionCall1(textin, CStringGetDatum(actiontree)); /* ev_action */
 
        /*
         * create a new pg_rewrite tuple
@@ -423,26 +423,27 @@ setRuleCheckAsUser_walker(Node *node, Oid *context)
  * ON SELECT rule associated with a view, when the view is renamed.
  */
 void
-RenameRewriteRule(char *oldname, char *newname)
+RenameRewriteRule(Oid owningRel, const char *oldName,
+                                 const char *newName)
 {
        Relation        pg_rewrite_desc;
        HeapTuple       ruletup;
 
        pg_rewrite_desc = heap_openr(RewriteRelationName, RowExclusiveLock);
 
-       ruletup = SearchSysCacheCopy(RULENAME,
-                                                                PointerGetDatum(oldname),
-                                                                0, 0, 0);
+       ruletup = SearchSysCacheCopy(RULERELNAME,
+                                                                ObjectIdGetDatum(owningRel),
+                                                                PointerGetDatum(oldName),
+                                                                0, 0);
        if (!HeapTupleIsValid(ruletup))
-               elog(ERROR, "RenameRewriteRule: rule \"%s\" does not exist", oldname);
+               elog(ERROR, "RenameRewriteRule: rule \"%s\" does not exist", oldName);
 
        /* should not already exist */
-       if (IsDefinedRewriteRule(newname))
+       if (IsDefinedRewriteRule(owningRel, newName))
                elog(ERROR, "Attempt to rename rule \"%s\" failed: \"%s\" already exists",
-                        oldname, newname);
+                        oldName, newName);
 
-       StrNCpy(NameStr(((Form_pg_rewrite) GETSTRUCT(ruletup))->rulename),
-                       newname, NAMEDATALEN);
+       namestrcpy(&(((Form_pg_rewrite) GETSTRUCT(ruletup))->rulename), newName);
 
        simple_heap_update(pg_rewrite_desc, &ruletup->t_self, ruletup);
 
index da8f1b8e5408dd385f419930aa3005148fd46186..df85fa504a055b0fd4cff31dd7f7e3175ba8531e 100644 (file)
@@ -8,15 +8,16 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.47 2002/03/29 19:06:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.48 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
-#include "utils/builtins.h"
+#include "access/genam.h"
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/indexing.h"
 #include "catalog/pg_rewrite.h"
 #include "commands/comment.h"
 #include "miscadmin.h"
 /*
  * RemoveRewriteRule
  *
- * Delete a rule given its (possibly qualified) rulename.
+ * Delete a rule given its name.
  */
 void
-RemoveRewriteRule(List *names)
+RemoveRewriteRule(Oid owningRel, const char *ruleName)
 {
-       char       *ruleName;
        Relation        RewriteRelation;
        Relation        event_relation;
        HeapTuple       tuple;
@@ -44,13 +44,6 @@ RemoveRewriteRule(List *names)
        bool            hasMoreRules;
        int32           aclcheck_result;
 
-       /*
-        * XXX temporary until rules become schema-tized
-        */
-       if (length(names) != 1)
-               elog(ERROR, "Qualified rule names not supported yet");
-       ruleName = strVal(lfirst(names));
-
        /*
         * Open the pg_rewrite relation.
         */
@@ -59,9 +52,10 @@ RemoveRewriteRule(List *names)
        /*
         * Find the tuple for the target rule.
         */
-       tuple = SearchSysCacheCopy(RULENAME,
+       tuple = SearchSysCacheCopy(RULERELNAME,
+                                                          ObjectIdGetDatum(owningRel),
                                                           PointerGetDatum(ruleName),
-                                                          0, 0, 0);
+                                                          0, 0);
 
        /*
         * complain if no rule with such name existed
@@ -75,6 +69,7 @@ RemoveRewriteRule(List *names)
         */
        ruleId = tuple->t_data->t_oid;
        eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
+       Assert(eventRelationOid == owningRel);
 
        /*
         * We had better grab AccessExclusiveLock so that we know no other
@@ -137,10 +132,10 @@ RemoveRewriteRule(List *names)
 void
 RelationRemoveRules(Oid relid)
 {
-       Relation        RewriteRelation = NULL;
-       HeapScanDesc scanDesc = NULL;
+       Relation        RewriteRelation;
+       SysScanDesc scanDesc;
        ScanKeyData scanKeyData;
-       HeapTuple       tuple = NULL;
+       HeapTuple       tuple;
 
        /*
         * Open the pg_rewrite relation.
@@ -148,18 +143,21 @@ RelationRemoveRules(Oid relid)
        RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
 
        /*
-        * Scan the RuleRelation ('pg_rewrite') for all the tuples that has
-        * the same ev_class as relid (the relation to be removed).
+        * Scan pg_rewrite for all the tuples that have the same ev_class
+        * as relid (the relation to be removed).
         */
        ScanKeyEntryInitialize(&scanKeyData,
                                                   0,
                                                   Anum_pg_rewrite_ev_class,
                                                   F_OIDEQ,
                                                   ObjectIdGetDatum(relid));
-       scanDesc = heap_beginscan(RewriteRelation,
-                                                         0, SnapshotNow, 1, &scanKeyData);
 
-       while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
+       scanDesc = systable_beginscan(RewriteRelation,
+                                                                 RewriteRelRulenameIndex,
+                                                                 true, SnapshotNow,
+                                                                 1, &scanKeyData);
+
+       while (HeapTupleIsValid(tuple = systable_getnext(scanDesc)))
        {
                /* Delete any comments associated with this rule */
                DeleteComments(tuple->t_data->t_oid, RelationGetRelid(RewriteRelation));
@@ -167,6 +165,7 @@ RelationRemoveRules(Oid relid)
                simple_heap_delete(RewriteRelation, &tuple->t_self);
        }
 
-       heap_endscan(scanDesc);
+       systable_endscan(scanDesc);
+
        heap_close(RewriteRelation, RowExclusiveLock);
 }
index bc2f04932a477b6bb3872dd2f8d844eb75de9bac..62a951aaf6fc4d2b4b1269d633b786e857266a91 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.49 2001/08/12 21:35:19 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.50 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * Is there a rule by the given name?
  */
 bool
-IsDefinedRewriteRule(const char *ruleName)
+IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
 {
-       return SearchSysCacheExists(RULENAME,
+       return SearchSysCacheExists(RULERELNAME,
+                                                               ObjectIdGetDatum(owningRel),
                                                                PointerGetDatum(ruleName),
-                                                               0, 0, 0);
+                                                               0, 0);
 }
 
 /*
index bef1b8064c7b68089a969a6b5e3ff2cd867b53d1..d8c2065258b0ef4bbe151ccb367cf0da6a720388 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.260 2002/03/24 04:31:07 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.261 2002/04/18 20:01:09 tgl Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -1688,7 +1688,7 @@ PostgresMain(int argc, char *argv[], const char *username)
        if (!IsUnderPostmaster)
        {
                puts("\nPOSTGRES backend interactive interface ");
-               puts("$Revision: 1.260 $ $Date: 2002/03/24 04:31:07 $\n");
+               puts("$Revision: 1.261 $ $Date: 2002/04/18 20:01:09 $\n");
        }
 
        /*
@@ -2322,7 +2322,7 @@ CreateCommandTag(Node *parsetree)
                        tag = "CREATE";
                        break;
 
-               case T_DropTrigStmt:
+               case T_DropPropertyStmt:
                        tag = "DROP";
                        break;
 
index 63e6b5dd9b2184ccc8a453b0d2c6bade4644696b..24a1e3d2964133cfa0bacca89f22e531cfdb7b75 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.149 2002/04/15 05:22:04 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.150 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -312,11 +312,6 @@ ProcessUtility(Node *parsetree,
                                                        RemoveIndex(rel);
                                                        break;
 
-                                               case DROP_RULE:
-                                                       /* RemoveRewriteRule checks permissions */
-                                                       RemoveRewriteRule(names);
-                                                       break;
-
                                                case DROP_TYPE:
                                                        /* RemoveType does its own permissions checks */
                                                        RemoveType(names);
@@ -714,12 +709,24 @@ ProcessUtility(Node *parsetree,
                        CreateTrigger((CreateTrigStmt *) parsetree);
                        break;
 
-               case T_DropTrigStmt:
+               case T_DropPropertyStmt:
                        {
-                               DropTrigStmt *stmt = (DropTrigStmt *) parsetree;
+                               DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree;
+                               Oid             relId;
 
-                               DropTrigger(RangeVarGetRelid(stmt->relation, false),
-                                                       stmt->trigname);
+                               relId = RangeVarGetRelid(stmt->relation, false);
+
+                               switch (stmt->removeType)
+                               {
+                                       case DROP_RULE:
+                                               /* RemoveRewriteRule checks permissions */
+                                               RemoveRewriteRule(relId, stmt->property);
+                                               break;
+                                       case DROP_TRIGGER:
+                                               /* DropTrigger checks permissions */
+                                               DropTrigger(relId, stmt->property);
+                                               break;
+                               }
                        }
                        break;
 
index 501d5a2095fb14c479280d1d9f7de3585169b2e5..5207488405b57960766df91ef6abddc46011cddb 100644 (file)
@@ -3,7 +3,7 @@
  *                             back to source text
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.96 2002/04/11 20:00:04 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.97 2002/04/18 20:01:09 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -42,6 +42,7 @@
 
 #include "catalog/heap.h"
 #include "catalog/index.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_index.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
@@ -97,11 +98,10 @@ typedef struct
  * Global data
  * ----------
  */
-static char *rulename = NULL;
-static void *plan_getrule = NULL;
-static char *query_getrule = "SELECT * FROM pg_rewrite WHERE rulename = $1";
-static void *plan_getview = NULL;
-static char *query_getview = "SELECT * FROM pg_rewrite WHERE rulename = $1";
+static void *plan_getrulebyoid = NULL;
+static char *query_getrulebyoid = "SELECT * FROM pg_rewrite WHERE oid = $1";
+static void *plan_getviewrule = NULL;
+static char *query_getviewrule = "SELECT * FROM pg_rewrite WHERE ev_class = $1 AND rulename = $2";
 
 
 /* ----------
@@ -112,6 +112,7 @@ static char *query_getview = "SELECT * FROM pg_rewrite WHERE rulename = $1";
  * as a parameter, and append their text output to its contents.
  * ----------
  */
+static text *pg_do_getviewdef(Oid viewoid);
 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc);
 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc);
 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace);
@@ -156,21 +157,16 @@ static char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
 Datum
 pg_get_ruledef(PG_FUNCTION_ARGS)
 {
-       Name            rname = PG_GETARG_NAME(0);
+       Oid                     ruleoid = PG_GETARG_OID(0);
        text       *ruledef;
        Datum           args[1];
-       char            nulls[2];
+       char            nulls[1];
        int                     spirc;
        HeapTuple       ruletup;
        TupleDesc       rulettc;
        StringInfoData buf;
        int                     len;
 
-       /*
-        * We need the rules name somewhere deep down: rulename is global
-        */
-       rulename = pstrdup(NameStr(*rname));
-
        /*
         * Connect to SPI manager
         */
@@ -182,27 +178,26 @@ pg_get_ruledef(PG_FUNCTION_ARGS)
         * pg_rewrite over the SPI manager instead of using the syscache to be
         * checked for read access on pg_rewrite.
         */
-       if (plan_getrule == NULL)
+       if (plan_getrulebyoid == NULL)
        {
                Oid                     argtypes[1];
                void       *plan;
 
-               argtypes[0] = NAMEOID;
-               plan = SPI_prepare(query_getrule, 1, argtypes);
+               argtypes[0] = OIDOID;
+               plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
                if (plan == NULL)
-                       elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getrule);
-               plan_getrule = SPI_saveplan(plan);
+                       elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getrulebyoid);
+               plan_getrulebyoid = SPI_saveplan(plan);
        }
 
        /*
         * Get the pg_rewrite tuple for this rule
         */
-       args[0] = PointerGetDatum(rulename);
-       nulls[0] = (rulename == NULL) ? 'n' : ' ';
-       nulls[1] = '\0';
-       spirc = SPI_execp(plan_getrule, args, nulls, 1);
+       args[0] = ObjectIdGetDatum(ruleoid);
+       nulls[0] = ' ';
+       spirc = SPI_execp(plan_getrulebyoid, args, nulls, 1);
        if (spirc != SPI_OK_SELECT)
-               elog(ERROR, "failed to get pg_rewrite tuple for %s", rulename);
+               elog(ERROR, "failed to get pg_rewrite tuple for %u", ruleoid);
        if (SPI_processed != 1)
        {
                if (SPI_finish() != SPI_OK_FINISH)
@@ -248,22 +243,48 @@ pg_get_ruledef(PG_FUNCTION_ARGS)
 Datum
 pg_get_viewdef(PG_FUNCTION_ARGS)
 {
-       Name            vname = PG_GETARG_NAME(0);
+       /* By OID */
+       Oid                     viewoid = PG_GETARG_OID(0);
        text       *ruledef;
-       Datum           args[1];
-       char            nulls[1];
+
+       ruledef = pg_do_getviewdef(viewoid);
+       PG_RETURN_TEXT_P(ruledef);
+}
+
+Datum
+pg_get_viewdef_name(PG_FUNCTION_ARGS)
+{
+       /* By qualified name */
+       text       *viewname = PG_GETARG_TEXT_P(0);
+       RangeVar   *viewrel;
+       Oid                     viewoid;
+       text       *ruledef;
+
+       viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname,
+                                                                                                                          "get_viewdef"));
+       viewoid = RangeVarGetRelid(viewrel, false);
+
+       ruledef = pg_do_getviewdef(viewoid);
+       PG_RETURN_TEXT_P(ruledef);
+}
+
+/*
+ * Common code for by-OID and by-name variants of pg_get_viewdef
+ */
+static text *
+pg_do_getviewdef(Oid viewoid)
+{
+       text       *ruledef;
+       Datum           args[2];
+       char            nulls[2];
        int                     spirc;
        HeapTuple       ruletup;
        TupleDesc       rulettc;
        StringInfoData buf;
        int                     len;
+       char       *viewname;
        char       *name;
 
-       /*
-        * We need the view name somewhere deep down
-        */
-       rulename = pstrdup(NameStr(*vname));
-
        /*
         * Connect to SPI manager
         */
@@ -275,28 +296,31 @@ pg_get_viewdef(PG_FUNCTION_ARGS)
         * pg_rewrite over the SPI manager instead of using the syscache to be
         * checked for read access on pg_rewrite.
         */
-       if (plan_getview == NULL)
+       if (plan_getviewrule == NULL)
        {
-               Oid                     argtypes[1];
+               Oid                     argtypes[2];
                void       *plan;
 
-               argtypes[0] = NAMEOID;
-               plan = SPI_prepare(query_getview, 1, argtypes);
+               argtypes[0] = OIDOID;
+               argtypes[1] = NAMEOID;
+               plan = SPI_prepare(query_getviewrule, 2, argtypes);
                if (plan == NULL)
-                       elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getview);
-               plan_getview = SPI_saveplan(plan);
+                       elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getviewrule);
+               plan_getviewrule = SPI_saveplan(plan);
        }
 
        /*
-        * Get the pg_rewrite tuple for this rule: rulename is actually
-        * viewname here
+        * Get the pg_rewrite tuple for the view's SELECT rule
         */
-       name = MakeRetrieveViewRuleName(rulename);
-       args[0] = PointerGetDatum(name);
+       viewname = get_rel_name(viewoid);
+       name = MakeRetrieveViewRuleName(viewname);
+       args[0] = ObjectIdGetDatum(viewoid);
+       args[1] = PointerGetDatum(name);
        nulls[0] = ' ';
-       spirc = SPI_execp(plan_getview, args, nulls, 1);
+       nulls[1] = ' ';
+       spirc = SPI_execp(plan_getviewrule, args, nulls, 2);
        if (spirc != SPI_OK_SELECT)
-               elog(ERROR, "failed to get pg_rewrite tuple for view %s", rulename);
+               elog(ERROR, "failed to get pg_rewrite tuple for view %s", viewname);
        initStringInfo(&buf);
        if (SPI_processed != 1)
                appendStringInfo(&buf, "Not a view");
@@ -322,10 +346,7 @@ pg_get_viewdef(PG_FUNCTION_ARGS)
        if (SPI_finish() != SPI_OK_FINISH)
                elog(ERROR, "get_viewdef: SPI_finish() failed");
 
-       /*
-        * Easy - isn't it?
-        */
-       PG_RETURN_TEXT_P(ruledef);
+       return ruledef;
 }
 
 
@@ -633,8 +654,6 @@ deparse_expression(Node *expr, List *dpcontext, bool forceprefix)
        context.namespaces = dpcontext;
        context.varprefix = forceprefix;
 
-       rulename = "";                          /* in case of errors */
-
        get_rule_expr(expr, &context);
 
        return buf.data;
@@ -792,6 +811,7 @@ deparse_context_for_subplan(const char *name, List *tlist,
 static void
 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
 {
+       char       *rulename;
        char            ev_type;
        Oid                     ev_class;
        int2            ev_attr;
@@ -800,23 +820,38 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
        char       *ev_action;
        List       *actions = NIL;
        int                     fno;
+       Datum           dat;
        bool            isnull;
 
        /*
         * Get the attribute values from the rules tuple
         */
+       fno = SPI_fnumber(rulettc, "rulename");
+       dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       Assert(!isnull);
+       rulename = NameStr(*(DatumGetName(dat)));
+
        fno = SPI_fnumber(rulettc, "ev_type");
-       ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       Assert(!isnull);
+       ev_type = DatumGetChar(dat);
 
        fno = SPI_fnumber(rulettc, "ev_class");
-       ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       Assert(!isnull);
+       ev_class = DatumGetObjectId(dat);
 
        fno = SPI_fnumber(rulettc, "ev_attr");
-       ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       Assert(!isnull);
+       ev_attr = DatumGetInt16(dat);
 
        fno = SPI_fnumber(rulettc, "is_instead");
-       is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
+       Assert(!isnull);
+       is_instead = DatumGetBool(dat);
 
+       /* these could be nulls */
        fno = SPI_fnumber(rulettc, "ev_qual");
        ev_qual = SPI_getvalue(ruletup, rulettc, fno);
 
@@ -1051,8 +1086,8 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace)
                        break;
 
                default:
-                       elog(ERROR, "get_ruledef of %s: query command type %d not implemented yet",
-                                rulename, query->commandType);
+                       elog(ERROR, "get_query_def: unknown query command type %d",
+                                query->commandType);
                        break;
        }
 }
@@ -1901,9 +1936,7 @@ get_rule_expr(Node *node, deparse_context *context)
                        break;
 
                default:
-                       printf("\n%s\n", nodeToString(node));
-                       elog(ERROR, "get_ruledef of %s: unknown node type %d in get_rule_expr()",
-                                rulename, nodeTag(node));
+                       elog(ERROR, "get_rule_expr: unknown node type %d", nodeTag(node));
                        break;
        }
 }
index 9a8e76f4926c3fa03df024e495e9e821c63683e2..686fcc8416b02e8f37545cf3e7d70ac023f41a82 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.160 2002/04/12 20:38:29 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.161 2002/04/18 20:01:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -675,17 +675,18 @@ RelationBuildRuleLock(Relation relation)
 
        /*
         * open pg_rewrite and begin a scan
-        *
-        * XXX: there is no suitable index for this scan.  FIXME.
         */
        pg_rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock);
        pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc);
-       pg_rewrite_scan = systable_beginscan(pg_rewrite_desc, NULL, false,
+       pg_rewrite_scan = systable_beginscan(pg_rewrite_desc, 
+                                                                                RewriteRelRulenameIndex,
+                                                                                criticalRelcachesBuilt,
                                                                                 SnapshotNow,
                                                                                 1, &key);
 
        while (HeapTupleIsValid(pg_rewrite_tuple = systable_getnext(pg_rewrite_scan)))
        {
+               Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(pg_rewrite_tuple);
                bool            isnull;
                Datum           ruleaction;
                Datum           rule_evqual;
@@ -698,18 +699,11 @@ RelationBuildRuleLock(Relation relation)
 
                rule->ruleId = pg_rewrite_tuple->t_data->t_oid;
 
-               rule->event = DatumGetInt32(heap_getattr(pg_rewrite_tuple,
-                                                                                                Anum_pg_rewrite_ev_type,
-                                                                                                pg_rewrite_tupdesc,
-                                                                                                &isnull)) - 48;
-               rule->attrno = DatumGetInt16(heap_getattr(pg_rewrite_tuple,
-                                                                                                 Anum_pg_rewrite_ev_attr,
-                                                                                                 pg_rewrite_tupdesc,
-                                                                                                 &isnull));
-               rule->isInstead = DatumGetBool(heap_getattr(pg_rewrite_tuple,
-                                                                                         Anum_pg_rewrite_is_instead,
-                                                                                                       pg_rewrite_tupdesc,
-                                                                                                       &isnull));
+               rule->event = rewrite_form->ev_type - '0';
+               rule->attrno = rewrite_form->ev_attr;
+               rule->isInstead = rewrite_form->is_instead;
+
+               /* Must use heap_getattr to fetch ev_qual and ev_action */
 
                ruleaction = heap_getattr(pg_rewrite_tuple,
                                                                  Anum_pg_rewrite_ev_action,
index 5deea860897597358751efdb40cb07b3be8f2e62..03acac91b02279cdf6072bd2a1a64e835d5f33bc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.78 2002/04/17 20:57:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.79 2002/04/18 20:01:10 tgl Exp $
  *
  * NOTES
  *       These routines allow the parser/planner/executor to perform
@@ -333,14 +333,14 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
        }},
-       {RewriteRelationName,           /* RULENAME */
-               RewriteRulenameIndex,
+       {RewriteRelationName,           /* RULERELNAME */
+               RewriteRelRulenameIndex,
                Anum_pg_rewrite_ev_class,
-               1,
+               2,
                {
+                       Anum_pg_rewrite_ev_class,
                        Anum_pg_rewrite_rulename,
                        0,
-                       0,
                        0
        }},
        {ShadowRelationName,            /* SHADOWNAME */
index 03fa12a8462c7e9d91900f6e89471e7f0e2ee53e..efacbe6c31a637d74b363bec64a0e264cbe543ce 100644 (file)
@@ -27,7 +27,7 @@
 # Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.148 2002/04/15 22:33:21 tgl Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.149 2002/04/18 20:01:10 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -689,19 +689,21 @@ CREATE VIEW pg_user AS \
 
 CREATE VIEW pg_rules AS \
     SELECT \
+        N.nspname AS schemaname, \
         C.relname AS tablename, \
         R.rulename AS rulename, \
-        pg_get_ruledef(R.rulename) AS definition \
-    FROM pg_rewrite R, pg_class C \
-    WHERE R.rulename !~ '^_RET' \
-        AND C.oid = R.ev_class;
+        pg_get_ruledef(R.oid) AS definition \
+    FROM (pg_rewrite R JOIN pg_class C ON (C.oid = R.ev_class)) \
+        LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) \
+    WHERE R.rulename !~ '^_RET';
 
 CREATE VIEW pg_views AS \
     SELECT \
+        N.nspname AS schemaname, \
         C.relname AS viewname, \
         pg_get_userbyid(C.relowner) AS viewowner, \
-        pg_get_viewdef(C.relname) AS definition \
-    FROM pg_class C \
+        pg_get_viewdef(C.oid) AS definition \
+    FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) \
     WHERE C.relkind = 'v';
 
 -- XXX why does pg_tables include sequences?
index f1cf4854f5e54d07c609ebf9ed94ec8cf367bcfa..2c5d14e5f86c661380b45766ea0a55cba00b7034 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.248 2002/04/13 19:57:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.249 2002/04/18 20:01:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2274,17 +2274,28 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs, const char *tablename)
                        PGresult   *res2;
 
                        resetPQExpBuffer(query);
-                       appendPQExpBuffer(query, "SELECT definition as viewdef, ");
 
-                       /*
-                        * XXX 7.2 - replace with att from pg_views or some other
-                        * generic source
-                        */
-                       appendPQExpBuffer(query, "(select oid from pg_rewrite where "
-                                         " rulename=('_RET' || viewname)::name) as view_oid"
-                                                         " from pg_views where viewname = ");
-                       formatStringLiteral(query, tblinfo[i].relname, CONV_ALL);
-                       appendPQExpBuffer(query, ";");
+                       if (g_fout->remoteVersion < 70300)
+                       {
+                               appendPQExpBuffer(query, "SELECT definition as viewdef, "
+                                                                 "(select oid from pg_rewrite where "
+                                                                 " rulename=('_RET' || viewname)::name) as view_oid"
+                                                                 " from pg_views where viewname = ");
+                               formatStringLiteral(query, tblinfo[i].relname, CONV_ALL);
+                               appendPQExpBuffer(query, ";");
+                       }
+                       else
+                       {
+                               /* Beginning in 7.3, viewname is not unique; use OID */
+                               appendPQExpBuffer(query, "SELECT pg_get_viewdef(ev_class) as viewdef, "
+                                                                 "oid as view_oid"
+                                                                 " from pg_rewrite where"
+                                                                 " ev_class = '%s'::oid and"
+                                                                 " rulename = ('_RET' || ",
+                                                                 tblinfo[i].oid);
+                               formatStringLiteral(query, tblinfo[i].relname, CONV_ALL);
+                               appendPQExpBuffer(query, ")::name;");
+                       }
 
                        res2 = PQexec(g_conn, query->data);
                        if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK)
@@ -4995,23 +5006,41 @@ dumpRules(Archive *fout, const char *tablename,
                        continue;
 
                /*
-                * Get all rules defined for this table We include pg_rules in the
-                * cross since it filters out all view rules (pjw 15-Sep-2000).
-                *
-                * XXXX: Use LOJ here
+                * Get all rules defined for this table
                 */
                resetPQExpBuffer(query);
-               appendPQExpBuffer(query, "SELECT definition,"
-                                                 "   (select usename from pg_user where pg_class.relowner = usesysid) AS viewowner, "
-                                                 "   pg_rewrite.oid, pg_rewrite.rulename "
-                                                 "FROM pg_rewrite, pg_class, pg_rules "
-                                                 "WHERE pg_class.relname = ");
-               formatStringLiteral(query, tblinfo[t].relname, CONV_ALL);
-               appendPQExpBuffer(query,
-                                                 "    AND pg_rewrite.ev_class = pg_class.oid "
-                                                 "    AND pg_rules.tablename = pg_class.relname "
-                                          "    AND pg_rules.rulename = pg_rewrite.rulename "
-                                                 "ORDER BY pg_rewrite.oid");
+
+               if (g_fout->remoteVersion < 70300)
+               {
+                       /*
+                        * We include pg_rules in the cross since it filters out all view
+                        * rules (pjw 15-Sep-2000).
+                        */
+                       appendPQExpBuffer(query, "SELECT definition,"
+                                                         "   (select usename from pg_user where pg_class.relowner = usesysid) AS viewowner, "
+                                                         "   pg_rewrite.oid, pg_rewrite.rulename "
+                                                         "FROM pg_rewrite, pg_class, pg_rules "
+                                                         "WHERE pg_class.relname = ");
+                       formatStringLiteral(query, tblinfo[t].relname, CONV_ALL);
+                       appendPQExpBuffer(query,
+                                                         "    AND pg_rewrite.ev_class = pg_class.oid "
+                                                         "    AND pg_rules.tablename = pg_class.relname "
+                                                         "    AND pg_rules.rulename = pg_rewrite.rulename "
+                                                         "ORDER BY pg_rewrite.oid");
+               }
+               else
+               {
+                       appendPQExpBuffer(query, "SELECT pg_get_ruledef(pg_rewrite.oid) AS definition,"
+                                                         " (select usename from pg_user where pg_class.relowner = usesysid) AS viewowner, "
+                                                         " pg_rewrite.oid, pg_rewrite.rulename "
+                                                         "FROM pg_rewrite, pg_class "
+                                                         "WHERE pg_class.oid = '%s'::oid "
+                                                         " AND pg_rewrite.ev_class = pg_class.oid "
+                                                         " AND pg_rewrite.rulename !~ '^_RET' "
+                                                         "ORDER BY pg_rewrite.oid",
+                                                         tblinfo[t].oid);
+               }
+
                res = PQexec(g_conn, query->data);
                if (!res ||
                        PQresultStatus(res) != PGRES_TUPLES_OK)
@@ -5041,6 +5070,7 @@ dumpRules(Archive *fout, const char *tablename,
 
                        resetPQExpBuffer(query);
                        appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename), force_quotes));
+                       appendPQExpBuffer(query, " ON %s", fmtId(tblinfo[t].relname, force_quotes));
                        dumpComment(fout, query->data, PQgetvalue(res, i, i_oid),
                                                "pg_rewrite", 0, NULL);
 
index 492c3e9b3fe1a0a2255b377f9bc38c651335c59f..4d6742fdbd076459a9c7ec02791d01285a61fca5 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.117 2002/04/17 20:57:56 tgl Exp $
+ * $Id: catversion.h,v 1.118 2002/04/18 20:01:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200204171
+#define CATALOG_VERSION_NO     200204181
 
 #endif
index b2b3f1f39c718ab335e58a309abb0f8cdeb6e6cb..e08e3aa8e9617dd08365f4bbe8e101435ac90f68 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: indexing.h,v 1.64 2002/04/17 20:57:56 tgl Exp $
+ * $Id: indexing.h,v 1.65 2002/04/18 20:01:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -80,7 +80,7 @@
 #define ProcedureOidIndex                      "pg_proc_oid_index"
 #define RelCheckIndex                          "pg_relcheck_rcrelid_index"
 #define RewriteOidIndex                                "pg_rewrite_oid_index"
-#define RewriteRulenameIndex           "pg_rewrite_rulename_index"
+#define RewriteRelRulenameIndex                "pg_rewrite_rel_rulename_index"
 #define ShadowNameIndex                                "pg_shadow_usename_index"
 #define ShadowSysidIndex                       "pg_shadow_usesysid_index"
 #define StatisticRelidAttnumIndex      "pg_statistic_relid_att_index"
@@ -178,7 +178,7 @@ DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(prona
 /* This following index is not used for a cache and is not unique */
 DECLARE_INDEX(pg_relcheck_rcrelid_index on pg_relcheck using btree(rcrelid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index on pg_rewrite using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_rewrite_rulename_index on pg_rewrite using btree(rulename name_ops));
+DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));
 DECLARE_UNIQUE_INDEX(pg_shadow_usename_index on pg_shadow using btree(usename name_ops));
 DECLARE_UNIQUE_INDEX(pg_shadow_usesysid_index on pg_shadow using btree(usesysid int4_ops));
 DECLARE_UNIQUE_INDEX(pg_statistic_relid_att_index on pg_statistic using btree(starelid oid_ops, staattnum int2_ops));
index a7f77f1f7df1c26a3b6dcc8c217b5295d88c2e7c..f8863d9340f6818fc5702c3493d0b4bb6f6d56b3 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.227 2002/04/11 20:00:12 tgl Exp $
+ * $Id: pg_proc.h,v 1.228 2002/04/18 20:01:10 tgl Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -2150,9 +2150,11 @@ DATA(insert OID = 1639 (  oidge                             PGNSP PGUID 12 f t f t f i 2 16 "26 26" 10
 DESCR("greater-than-or-equal");
 
 /* System-view support functions */
-DATA(insert OID = 1640 (  pg_get_ruledef          PGNSP PGUID 12 f t f t f s 1 25 "19" 100 0 0 100  pg_get_ruledef - _null_ ));
+DATA(insert OID = 1573 (  pg_get_ruledef          PGNSP PGUID 12 f t f t f s 1 25 "26" 100 0 0 100  pg_get_ruledef - _null_ ));
 DESCR("source text of a rule");
-DATA(insert OID = 1641 (  pg_get_viewdef          PGNSP PGUID 12 f t f t f s 1 25 "19" 100 0 0 100  pg_get_viewdef - _null_ ));
+DATA(insert OID = 1640 (  pg_get_viewdef          PGNSP PGUID 12 f t f t f s 1 25 "25" 100 0 0 100  pg_get_viewdef_name - _null_ ));
+DESCR("select statement of a view");
+DATA(insert OID = 1641 (  pg_get_viewdef          PGNSP PGUID 12 f t f t f s 1 25 "26" 100 0 0 100  pg_get_viewdef - _null_ ));
 DESCR("select statement of a view");
 DATA(insert OID = 1642 (  pg_get_userbyid         PGNSP PGUID 12 f t f t f s 1 19 "23" 100 0 0 100  pg_get_userbyid - _null_ ));
 DESCR("user name by UID (with fallback)");
index 46b73bc0838420ef7c0a6afd43eaf7f7c668dd50..00b0eb29746f1c4ccf3d2c727a6ac1b49b1a81e6 100644 (file)
@@ -4,11 +4,14 @@
  *       definition of the system "rewrite-rule" relation (pg_rewrite)
  *       along with the relation's initial contents.
  *
+ * As of Postgres 7.3, the primary key for this table is <ev_class, rulename>
+ * --- ie, rule names are only unique among the rules of a given table.
+ *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_rewrite.h,v 1.17 2001/11/05 17:46:32 momjian Exp $
+ * $Id: pg_rewrite.h,v 1.18 2002/04/18 20:01:11 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -34,9 +37,9 @@
 CATALOG(pg_rewrite)
 {
        NameData        rulename;
-       char            ev_type;
        Oid                     ev_class;
        int2            ev_attr;
+       char            ev_type;
        bool            is_instead;
 
        /* NB: remaining fields must be accessed via heap_getattr */
@@ -57,9 +60,9 @@ typedef FormData_pg_rewrite *Form_pg_rewrite;
  */
 #define Natts_pg_rewrite                               7
 #define Anum_pg_rewrite_rulename               1
-#define Anum_pg_rewrite_ev_type                        2
-#define Anum_pg_rewrite_ev_class               3
-#define Anum_pg_rewrite_ev_attr                        4
+#define Anum_pg_rewrite_ev_class               2
+#define Anum_pg_rewrite_ev_attr                        3
+#define Anum_pg_rewrite_ev_type                        4
 #define Anum_pg_rewrite_is_instead             5
 #define Anum_pg_rewrite_ev_qual                        6
 #define Anum_pg_rewrite_ev_action              7
index ff03eb122845722e46089176cf21046d08afdae7..1664e769003acc7e8d291c6f6ad68bc1a8f687c3 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.104 2002/04/05 11:56:54 momjian Exp $
+ * $Id: nodes.h,v 1.105 2002/04/18 20:01:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -181,7 +181,7 @@ typedef enum NodeTag
        T_VariableShowStmt,
        T_VariableResetStmt,
        T_CreateTrigStmt,
-       T_DropTrigStmt,
+       T_DropPropertyStmt,
        T_CreatePLangStmt,
        T_DropPLangStmt,
        T_CreateUserStmt,
index ba9ed9aa8de14e18343f5319ce4261a9519ff90a..dc2eabb5b2244a57a257ca794debde81d147399c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.171 2002/04/17 20:57:57 tgl Exp $
+ * $Id: parsenodes.h,v 1.172 2002/04/18 20:01:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -940,13 +940,6 @@ typedef struct CreateTrigStmt
        RangeVar   *constrrel;          /* opposite relation */
 } CreateTrigStmt;
 
-typedef struct DropTrigStmt
-{
-       NodeTag         type;
-       char       *trigname;           /* TRIGGER' name */
-       RangeVar   *relation;           /* triggered relation */
-} DropTrigStmt;
-
 /* ----------------------
  *             Create/Drop PROCEDURAL LANGUAGE Statement
  * ----------------------
@@ -1060,7 +1053,7 @@ typedef struct CreateDomainStmt
 } CreateDomainStmt;
 
 /* ----------------------
- *             Drop Table|Sequence|View|Index|Rule|Type Statement
+ *             Drop Table|Sequence|View|Index|Type|Domain Statement
  * ----------------------
  */
 
@@ -1068,9 +1061,8 @@ typedef struct CreateDomainStmt
 #define DROP_SEQUENCE 2
 #define DROP_VIEW        3
 #define DROP_INDEX       4
-#define DROP_RULE        5
-#define DROP_TYPE     6
-#define DROP_DOMAIN      7
+#define DROP_TYPE     5
+#define DROP_DOMAIN      6
 
 typedef struct DropStmt
 {
@@ -1080,6 +1072,25 @@ typedef struct DropStmt
        int                     behavior;               /* CASCADE or RESTRICT drop behavior */
 } DropStmt;
 
+/* ----------------------
+ *             Drop Rule|Trigger Statement
+ *
+ * In general this may be used for dropping any property of a relation;
+ * for example, someday soon we may have DROP ATTRIBUTE.
+ * ----------------------
+ */
+
+#define DROP_RULE        100
+#define DROP_TRIGGER  101
+
+typedef struct DropPropertyStmt
+{
+       NodeTag         type;
+       RangeVar   *relation;           /* owning relation */
+       char       *property;           /* name of rule, trigger, etc */
+       int                     removeType;
+} DropPropertyStmt;
+
 /* ----------------------
  *                             Truncate Table Statement
  * ----------------------
index a9f7792a612a3e1e8ef317f747e29bf6a99885b1..4bf20a2ca767ec261ec37758fe2a8cd5ed11b89a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteDefine.h,v 1.13 2001/11/05 17:46:35 momjian Exp $
+ * $Id: rewriteDefine.h,v 1.14 2002/04/18 20:01:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 
 extern void DefineQueryRewrite(RuleStmt *args);
 
-extern void RenameRewriteRule(char *oldname, char *newname);
+extern void RenameRewriteRule(Oid owningRel, const char *oldName,
+                                                         const char *newName);
 
 #endif   /* REWRITEDEFINE_H */
index ac79e6c919bf068d7e95dfc88a73e71b23d8159b..3aa4cbdf53202f65fd8e91afe4ae4f7cc44d437c 100644 (file)
@@ -7,14 +7,14 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteRemove.h,v 1.12 2002/03/29 19:06:26 tgl Exp $
+ * $Id: rewriteRemove.h,v 1.13 2002/04/18 20:01:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef REWRITEREMOVE_H
 #define REWRITEREMOVE_H
 
-extern void RemoveRewriteRule(List *names);
+extern void RemoveRewriteRule(Oid owningRel, const char *ruleName);
 extern void RelationRemoveRules(Oid relid);
 
 #endif   /* REWRITEREMOVE_H */
index 6f955d6eea311b07120c05902e1fa9ad59cc6666..7453dd995821b2fd67dd739936fcae6c752c3705 100644 (file)
@@ -7,14 +7,14 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteSupport.h,v 1.20 2001/11/05 17:46:35 momjian Exp $
+ * $Id: rewriteSupport.h,v 1.21 2002/04/18 20:01:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef REWRITESUPPORT_H
 #define REWRITESUPPORT_H
 
-extern bool IsDefinedRewriteRule(const char *ruleName);
+extern bool IsDefinedRewriteRule(Oid owningRel, const char *ruleName);
 
 extern char *MakeRetrieveViewRuleName(const char *view_name);
 
index b38f4429cb059ae001dec8d9e9970e2c6a20d7ad..caa2c571029fc258c7aa2068786d32098c6b4faf 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.176 2002/04/11 20:00:17 tgl Exp $
+ * $Id: builtins.h,v 1.177 2002/04/18 20:01:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -337,6 +337,7 @@ extern Datum regproctooid(PG_FUNCTION_ARGS);
 /* ruleutils.c */
 extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);
 extern Datum pg_get_viewdef(PG_FUNCTION_ARGS);
+extern Datum pg_get_viewdef_name(PG_FUNCTION_ARGS);
 extern Datum pg_get_indexdef(PG_FUNCTION_ARGS);
 extern Datum pg_get_userbyid(PG_FUNCTION_ARGS);
 extern Datum pg_get_expr(PG_FUNCTION_ARGS);
index dbe50b37be63045b5b9edf1fa8f676fdacce0333..a5282a97536aae3902c0f98cc1ae5c2da28f3e11 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: syscache.h,v 1.46 2002/04/17 20:57:57 tgl Exp $
+ * $Id: syscache.h,v 1.47 2002/04/18 20:01:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,7 +52,7 @@
 #define PROCOID                        21
 #define RELNAMENSP             22
 #define RELOID                 23
-#define RULENAME               24
+#define RULERELNAME            24
 #define SHADOWNAME             25
 #define SHADOWSYSID            26
 #define STATRELATT             27
index 27a7b38dd4819754d900e90ac0149b3c88c8ca33..2d90066fc72e7c8a6a27bf121218e897b912ea3b 100644 (file)
@@ -217,13 +217,13 @@ ERROR:  parser: parse error at or near ";"
 drop rule 314159;
 ERROR:  parser: parse error at or near "314159"
 -- no such rule 
-drop rule nonesuch;
-ERROR:  Rule "nonesuch" not found
+drop rule nonesuch on noplace;
+ERROR:  Relation "noplace" does not exist
 -- bad keyword 
 drop tuple rule nonesuch;
 ERROR:  parser: parse error at or near "tuple"
 -- no such rule 
-drop instance rule nonesuch;
+drop instance rule nonesuch on noplace;
 ERROR:  parser: parse error at or near "instance"
 -- no such rule 
 drop rewrite rule nonesuch;
index 8e0d9e3239b4f75b7fde1976962f5456df81f26f..75578b76e0435088611db583bb87f5f79657179d 100644 (file)
@@ -648,8 +648,8 @@ select * from rtest_order2;
 ---+---+-------------------------------------
  1 | 1 | rule 2 - this should run 1st
  1 | 2 | rule 4 - this should run 2nd
- 1 | 3 | rule 3 - this should run 3rd or 4th
- 1 | 4 | rule 1 - this should run 3rd or 4th
+ 1 | 3 | rule 1 - this should run 3rd or 4th
+ 1 | 4 | rule 3 - this should run 3rd or 4th
 (4 rows)
 
 --
@@ -1173,7 +1173,7 @@ select * from foo;
  1001
 (1 row)
 
-drop rule foorule;
+drop rule foorule on foo;
 -- this should fail because f1 is not exposed for unqualified reference:
 create rule foorule as on insert to foo where f1 < 100
 do instead insert into foo2 values (f1);
@@ -1196,7 +1196,7 @@ select * from foo2;
   2
 (1 row)
 
-drop rule foorule;
+drop rule foorule on foo;
 drop table foo;
 drop table foo2;
 --
@@ -1256,7 +1256,7 @@ select * from cchild;
    2 | test2
 (2 rows)
 
-drop rule rrule;
+drop rule rrule on vview;
 drop view vview;
 drop table pparent;
 drop table cchild;
@@ -1268,7 +1268,7 @@ SELECT viewname, definition FROM pg_views ORDER BY viewname;
 --------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  iexit                    | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
  pg_indexes               | SELECT c.relname AS tablename, i.relname AS indexname, pg_get_indexdef(x.indexrelid) AS indexdef FROM pg_index x, pg_class c, pg_class i WHERE ((((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char")) AND (c.oid = x.indrelid)) AND (i.oid = x.indexrelid));
- pg_rules                 | SELECT c.relname AS tablename, r.rulename, pg_get_ruledef(r.rulename) AS definition FROM pg_rewrite r, pg_class c WHERE ((r.rulename !~ '^_RET'::text) AND (c.oid = r.ev_class));
+ pg_rules                 | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename !~ '^_RET'::text);
  pg_stat_activity         | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));
  pg_stat_all_indexes      | SELECT c.oid AS relid, i.oid AS indexrelid, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM pg_class c, pg_class i, pg_index x WHERE (((c.relkind = 'r'::"char") AND (x.indrelid = c.oid)) AND (x.indexrelid = i.oid));
  pg_stat_all_tables       | SELECT c.oid AS relid, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, sum(pg_stat_get_numscans(i.indexrelid)) AS idx_scan, sum(pg_stat_get_tuples_fetched(i.indexrelid)) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del FROM (pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, c.relname;
@@ -1289,7 +1289,7 @@ SELECT viewname, definition FROM pg_views ORDER BY viewname;
  pg_stats                 | SELECT c.relname AS tablename, a.attname, s.stanullfrac AS null_frac, s.stawidth AS avg_width, s.stadistinct AS n_distinct, CASE WHEN (1 = s.stakind1) THEN s.stavalues1 WHEN (1 = s.stakind2) THEN s.stavalues2 WHEN (1 = s.stakind3) THEN s.stavalues3 WHEN (1 = s.stakind4) THEN s.stavalues4 ELSE NULL::"_text" END AS most_common_vals, CASE WHEN (1 = s.stakind1) THEN s.stanumbers1 WHEN (1 = s.stakind2) THEN s.stanumbers2 WHEN (1 = s.stakind3) THEN s.stanumbers3 WHEN (1 = s.stakind4) THEN s.stanumbers4 ELSE NULL::"_float4" END AS most_common_freqs, CASE WHEN (2 = s.stakind1) THEN s.stavalues1 WHEN (2 = s.stakind2) THEN s.stavalues2 WHEN (2 = s.stakind3) THEN s.stavalues3 WHEN (2 = s.stakind4) THEN s.stavalues4 ELSE NULL::"_text" END AS histogram_bounds, CASE WHEN (3 = s.stakind1) THEN s.stanumbers1[1] WHEN (3 = s.stakind2) THEN s.stanumbers2[1] WHEN (3 = s.stakind3) THEN s.stanumbers3[1] WHEN (3 = s.stakind4) THEN s.stanumbers4[1] ELSE NULL::float4 END AS correlation FROM pg_class c, pg_attribute a, pg_statistic s WHERE ((((c.oid = s.starelid) AND (c.oid = a.attrelid)) AND (a.attnum = s.staattnum)) AND has_table_privilege(c.oid, 'select'::text));
  pg_tables                | SELECT c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM pg_class c WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 's'::"char"));
  pg_user                  | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usetrace, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil, pg_shadow.useconfig FROM pg_shadow;
- pg_views                 | SELECT c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.relname) AS definition FROM pg_class c WHERE (c.relkind = 'v'::"char");
+ pg_views                 | SELECT n.nspname AS schemaname, c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.oid) AS definition FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'v'::"char");
  rtest_v1                 | SELECT rtest_t1.a, rtest_t1.b FROM rtest_t1;
  rtest_vcomp              | SELECT x.part, (x.size * y.factor) AS size_in_cm FROM rtest_comp x, rtest_unitfact y WHERE (x.unit = y.unit);
  rtest_vview1             | SELECT x.a, x.b FROM rtest_view1 x WHERE (0 < (SELECT count(*) AS count FROM rtest_view2 y WHERE (y.a = x.a)));
index 5ab09d2a1239a76f0b5be446b7139fc506002947..db041fa9cbfcc4127ec28ef21dd49fa363c6bfba 100644 (file)
@@ -239,13 +239,13 @@ drop rule;
 drop rule 314159;
 
 -- no such rule 
-drop rule nonesuch;
+drop rule nonesuch on noplace;
 
 -- bad keyword 
 drop tuple rule nonesuch;
 
 -- no such rule 
-drop instance rule nonesuch;
+drop instance rule nonesuch on noplace;
 
 -- no such rule 
 drop rewrite rule nonesuch;
index 4322cf6cd2c458fb5d98293556825af6cf4cff73..01c202e11649d60210e3f5a1edd52db79d09227c 100644 (file)
@@ -699,7 +699,7 @@ insert into foo values(1);
 insert into foo values(1001);
 select * from foo;
 
-drop rule foorule;
+drop rule foorule on foo;
 
 -- this should fail because f1 is not exposed for unqualified reference:
 create rule foorule as on insert to foo where f1 < 100
@@ -714,7 +714,7 @@ insert into foo values(100);
 select * from foo;
 select * from foo2;
 
-drop rule foorule;
+drop rule foorule on foo;
 drop table foo;
 drop table foo2;
 
@@ -751,7 +751,7 @@ update vview set descrip='test3' where pid=3;
 select * from vview;
 select * from cchild;
 
-drop rule rrule;
+drop rule rrule on vview;
 drop view vview;
 drop table pparent;
 drop table cchild;