]> granicus.if.org Git - postgresql/commitdiff
Hello.
authorBruce Momjian <bruce@momjian.us>
Tue, 26 Oct 1999 03:12:39 +0000 (03:12 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 26 Oct 1999 03:12:39 +0000 (03:12 +0000)
The following patch extends the COMMENT ON functionality to the
rest of the database objects beyond just tables, columns, and views. The
grammer of the COMMENT ON statement now looks like:

COMMENT ON [
  [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <objname>
|

  COLUMN <relation>.<attribute> |
  AGGREGATE <aggname> <aggtype> |
  FUNCTION <funcname> (arg1, arg2, ...) |
  OPERATOR <op> (leftoperand_typ rightoperand_typ) |
  TRIGGER <triggername> ON relname>

Mike Mascari
(mascarim@yahoo.com)

15 files changed:
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/commands/Makefile
src/backend/commands/comment.c [new file with mode: 0644]
src/backend/commands/creatinh.c
src/backend/commands/dbcommands.c
src/backend/commands/remove.c
src/backend/commands/trigger.c
src/backend/parser/gram.y
src/backend/rewrite/rewriteRemove.c
src/backend/tcop/utility.c
src/include/catalog/heap.h
src/include/commands/comment.h [new file with mode: 0644]
src/include/commands/creatinh.h
src/include/nodes/parsenodes.h

index bd0a8668d0fe97a0f126672736ea2c64df6f7d07..eb934f6d3d94b98b6aec1697b156d99b9567e9a4 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.104 1999/10/15 01:49:39 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.105 1999/10/26 03:12:33 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -45,6 +45,7 @@
 #include "catalog/pg_proc.h"
 #include "catalog/pg_relcheck.h"
 #include "catalog/pg_type.h"
+#include "commands/comment.h"
 #include "commands/trigger.h"
 #include "optimizer/clauses.h"
 #include "optimizer/planmain.h"
@@ -1276,146 +1277,18 @@ DeleteAttributeTuples(Relation rel)
                                                                   Int16GetDatum(attnum),
                                                                                                                   0, 0)))
                {
-                     DeleteComments(tup->t_data->t_oid);
-                     heap_delete(pg_attribute_desc, &tup->t_self, NULL);
-                     pfree(tup);
-               }
-       }
-
-       heap_close(pg_attribute_desc, RowExclusiveLock);
-}
-
-/* ----------------------------------------------------------
- *  CreateComments
- * 
- *  This routine is handed the oid and the command associated
- *  with that id and will insert, update, or delete (if the 
- *  comment is an empty string or a NULL pointer) the associated
- *  comment from the system cataloge, pg_description. 
- *
- * ----------------------------------------------------------
- */
-
-void
-CreateComments(Oid oid, char *comment)
-{
+                 
+                 /*** Delete any comments associated with this attribute ***/
 
-  Relation description;
-  TupleDesc tupDesc;
-  HeapScanDesc scan;
-  ScanKeyData entry;
-  HeapTuple desctuple, searchtuple;
-  Datum values[Natts_pg_description];
-  char nulls[Natts_pg_description];
-  char replaces[Natts_pg_description];
-  bool modified = false;
-  int i;
-
-  /*** Open pg_description, form a new tuple, if necessary ***/
-
-  description = heap_openr(DescriptionRelationName, RowExclusiveLock);
-  tupDesc = description->rd_att;
-  if ((comment != NULL) && (strlen(comment) > 0)) {
-    for (i = 0; i < Natts_pg_description; i++) {
-      nulls[i] = ' ';
-      replaces[i] = 'r';
-      values[i] = (Datum) NULL;
-    }
-    i = 0;
-    values[i++] = ObjectIdGetDatum(oid);
-    values[i++] = (Datum) fmgr(F_TEXTIN, comment);
-  }
-
-  /*** Now, open pg_description and attempt to find the old tuple ***/
-  
-  ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
-                        ObjectIdGetDatum(oid));
-  scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
-  searchtuple = heap_getnext(scan, 0);
-
-  /*** If a previous tuple exists, either delete it or prepare a replacement ***/
-
-  if (HeapTupleIsValid(searchtuple)) {
-        
-    /*** If the comment is blank, call heap_delete, else heap_replace ***/
-
-    if ((comment == NULL) || (strlen(comment) == 0)) {
-      heap_delete(description, &searchtuple->t_self, NULL);
-    } else {
-      desctuple = heap_modifytuple(searchtuple, description, values, nulls, replaces);      
-      setheapoverride(true);
-      heap_replace(description, &searchtuple->t_self, desctuple, NULL);
-      setheapoverride(false);
-      modified = TRUE;
-    }
-
-  } else {    
-    desctuple = heap_formtuple(tupDesc, values, nulls);
-    heap_insert(description, desctuple);
-    modified = TRUE;
-  }
-
-  /*** Complete the scan, update indices, if necessary ***/
-
-  heap_endscan(scan);
-  
-  if (modified) {
-    if (RelationGetForm(description)->relhasindex) {
-      Relation idescs[Num_pg_description_indices];
-      
-      CatalogOpenIndices(Num_pg_description_indices, Name_pg_description_indices, idescs);
-      CatalogIndexInsert(idescs, Num_pg_description_indices, description, desctuple);
-      CatalogCloseIndices(Num_pg_description_indices, idescs);
-    }
-    pfree(desctuple);
-
-  }
-
-  heap_close(description, RowExclusiveLock);
+                 DeleteComments(tup->t_data->t_oid);
 
-}
-    
-/* --------------------------------
- *  DeleteComments
- *
- *  This routine is used to purge any comments 
- *  associated with the Oid handed to this routine,
- *  regardless of the actual object type. It is
- *  called, for example, when a relation is destroyed.
- * --------------------------------
- */
+                 heap_delete(pg_attribute_desc, &tup->t_self, NULL);
+                 pfree(tup);
 
-void 
-DeleteComments(Oid oid) 
-{
+               }
+       }
 
-  Relation description;
-  TupleDesc tupDesc;
-  ScanKeyData entry;
-  HeapScanDesc scan;
-  HeapTuple searchtuple;
-
-  description = heap_openr(DescriptionRelationName, RowExclusiveLock);
-  tupDesc = description->rd_att;
-
-  /*** Now, open pg_description and attempt to find the old tuple ***/
-  
-  ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
-                        ObjectIdGetDatum(oid));
-  scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
-  searchtuple = heap_getnext(scan, 0);
-
-  /*** If a previous tuple exists, delete it ***/
-
-  if (HeapTupleIsValid(searchtuple)) {    
-    heap_delete(description, &searchtuple->t_self, NULL);
-  } 
-  
-  /*** Complete the scan, update indices, if necessary ***/
-
-  heap_endscan(scan);
-  heap_close(description, RowExclusiveLock);
-  
+       heap_close(pg_attribute_desc, RowExclusiveLock);
 }
 
 /* --------------------------------
@@ -1529,6 +1402,7 @@ DeleteTypeTuple(Relation rel)
         *      we release the read lock on pg_type.  -mer 13 Aug 1991
         * ----------------
         */
+       
        heap_delete(pg_type_desc, &tup->t_self, NULL);
 
        heap_endscan(pg_type_scan);
index f8c4dac95e77278290f56b13ecf300cc03dcf43b..9e7850f8f637a9254a896815b7a27dcbccc1ffef 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.91 1999/09/24 00:24:11 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.92 1999/10/26 03:12:33 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -32,6 +32,7 @@
 #include "catalog/pg_index.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
+#include "commands/comment.h"
 #include "executor/executor.h"
 #include "miscadmin.h"
 #include "optimizer/clauses.h"
@@ -1127,6 +1128,13 @@ index_destroy(Oid indexId)
        if (IsTransactionBlock() && ! userindexRelation->rd_myxactonly)
                elog(NOTICE, "Caution: DROP INDEX cannot be rolled back, so don't abort now");
 
+       /* ----------------
+        * fix DESCRIPTION relation
+        * ----------------
+        */
+
+       DeleteComments(indexId);
+       
        /* ----------------
         * fix RELATION relation
         * ----------------
index 3b4d3a8d3179fae6c14ce581dc0893460f49b465..fa1c4495e59d974ade045332d391c03946c3f49f 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for commands
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.18 1999/02/27 21:42:33 tgl Exp $
+#    $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.19 1999/10/26 03:12:34 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -17,7 +17,7 @@ ifdef MULTIBYTE
 CFLAGS+= $(MBFLAGS)
 endif
 
-OBJS = async.o creatinh.o command.o copy.o indexcmds.o define.o \
+OBJS = async.o creatinh.o command.o comment.o copy.o indexcmds.o define.o \
        remove.o rename.o vacuum.o view.o cluster.o \
        explain.o sequence.o trigger.o user.o proclang.o \
        dbcommands.o variable.o
@@ -27,6 +27,12 @@ all: SUBSYS.o
 SUBSYS.o: $(OBJS)
        $(LD) -r -o SUBSYS.o $(OBJS)
 
+# The following declares a hard-coded dependency on parse.h since, 
+# if compiled without make dep, comment.c would get compiled before 
+# the parser. 
+
+comment.o: ../parse.h
+
 depend dep:
        $(CC) -MM $(CFLAGS) *.c >depend
 
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
new file mode 100644 (file)
index 0000000..c2dacaa
--- /dev/null
@@ -0,0 +1,796 @@
+/*-------------------------------------------------------------------------
+ *
+ * comment.c
+ *       
+ * PostgreSQL object comments utility code.
+ *
+ * Copyright (c) 1999, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/indexing.h"
+#include "catalog/heap.h"
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_database.h"
+#include "catalog/pg_description.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_rewrite.h"
+#include "catalog/pg_shadow.h"
+#include "catalog/pg_trigger.h"
+#include "catalog/pg_type.h"
+#include "commands/comment.h"
+#include "miscadmin.h"
+#include "rewrite/rewriteRemove.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/syscache.h"
+
+#include "../backend/parser/parse.h"
+
+/*------------------------------------------------------------------
+ * Static Function Prototypes --
+ * 
+ * The following protoypes are declared static so as not to conflict 
+ * with any other routines outside this module. These routines are 
+ * called by the public function CommentObject() routine to create 
+ * the appropriate comment for the specific object type.
+ *------------------------------------------------------------------
+ */
+
+static void CommentRelation(int objtype, char *relation, char *comment);
+static void CommentAttribute(char *relation, char *attrib, char *comment);
+static void CommentDatabase(char *database, char *comment);
+static void CommentRewrite(char *rule, char *comment);
+static void CommentType(char *type, char *comment);
+static void CommentAggregate(char *aggregate, char *aggtype, char *comment);
+static void CommentProc(char *function, List *arguments, char *comment);
+static void CommentOperator(char *opname, List *arguments, char *comment);
+static void CommentTrigger(char *trigger, char *relation, char *comments);
+
+/*------------------------------------------------------------------
+ * CommentObject --
+ *
+ * This routine is used to add the associated comment into 
+ * pg_description for the object specified by the paramters handed 
+ * to this routine. If the routine cannot determine an Oid to 
+ * associated with the parameters handed to this routine, an 
+ * error is thrown. Otherwise the comment is added to pg_description
+ * by calling the CreateComments() routine. If the comments were
+ * empty, CreateComments() will drop any comments associated with
+ * the object.
+ *------------------------------------------------------------------
+*/
+
+void CommentObject(int objtype, char *objname, char *objproperty, 
+                  List *objlist, char *comment) {
+  
+  switch (objtype) {
+  case (INDEX):
+  case (SEQUENCE):
+  case (TABLE):
+  case (VIEW):
+    CommentRelation(objtype, objname, comment);
+    break;
+  case (COLUMN):
+    CommentAttribute(objname, objproperty, comment);
+    break;
+  case (DATABASE):
+    CommentDatabase(objname, comment);
+    break;
+  case (RULE):
+    CommentRewrite(objname, comment);
+    break;
+  case (TYPE_P):
+    CommentType(objname, comment);
+    break;
+  case (AGGREGATE):
+    CommentAggregate(objname, objproperty, comment);
+    break;
+  case (FUNCTION):
+    CommentProc(objname, objlist, comment);
+    break;
+  case (OPERATOR):
+    CommentOperator(objname, objlist, comment);
+    break;
+  case (TRIGGER):
+    CommentTrigger(objname, objproperty, comment);
+    break;
+  default:
+    elog(ERROR, "An attempt was made to comment on a unkown type: %i",
+        objtype);    
+  }
+
+}
+
+/*------------------------------------------------------------------
+ * CreateComments --
+ * 
+ * This routine is handed the oid and the command associated
+ * with that id and will insert, update, or delete (if the 
+ * comment is an empty string or a NULL pointer) the associated
+ * comment from the system cataloge, pg_description. 
+ *
+ *------------------------------------------------------------------
+ */
+
+void CreateComments(Oid oid, char *comment) {
+
+  Relation description;
+  TupleDesc tupDesc;
+  HeapScanDesc scan;
+  ScanKeyData entry;
+  HeapTuple desctuple = NULL, searchtuple;
+  Datum values[Natts_pg_description];
+  char nulls[Natts_pg_description];
+  char replaces[Natts_pg_description];
+  bool modified = false;
+  int i;
+
+  /*** Open pg_description, form a new tuple, if necessary ***/
+
+  description = heap_openr(DescriptionRelationName, RowExclusiveLock);
+  tupDesc = description->rd_att;
+  if ((comment != NULL) && (strlen(comment) > 0)) {
+    for (i = 0; i < Natts_pg_description; i++) {
+      nulls[i] = ' ';
+      replaces[i] = 'r';
+      values[i] = (Datum) NULL;
+    }
+    i = 0;
+    values[i++] = ObjectIdGetDatum(oid);
+    values[i++] = (Datum) fmgr(F_TEXTIN, comment);
+  }
+
+  /*** Now, open pg_description and attempt to find the old tuple ***/
+  
+  ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
+                        ObjectIdGetDatum(oid));
+  scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
+  searchtuple = heap_getnext(scan, 0);
+
+  /*** If a previous tuple exists, either delete or prep replacement ***/
+
+  if (HeapTupleIsValid(searchtuple)) {
+        
+    /*** If the comment is blank, call heap_delete, else heap_replace ***/
+
+    if ((comment == NULL) || (strlen(comment) == 0)) {
+      heap_delete(description, &searchtuple->t_self, NULL);
+    } else {
+      desctuple = heap_modifytuple(searchtuple, description, values, 
+                                  nulls, replaces);      
+      setheapoverride(true);
+      heap_replace(description, &searchtuple->t_self, desctuple, NULL);
+      setheapoverride(false);
+      modified = TRUE;
+    }
+
+  } else {    
+    desctuple = heap_formtuple(tupDesc, values, nulls);
+    heap_insert(description, desctuple);
+    modified = TRUE;
+  }
+
+  /*** Complete the scan, update indices, if necessary ***/
+
+  heap_endscan(scan);
+  
+  if (modified) {
+    if (RelationGetForm(description)->relhasindex) {
+      Relation idescs[Num_pg_description_indices];
+      
+      CatalogOpenIndices(Num_pg_description_indices, 
+                        Name_pg_description_indices, idescs);
+      CatalogIndexInsert(idescs, Num_pg_description_indices, description, 
+                        desctuple);
+      CatalogCloseIndices(Num_pg_description_indices, idescs);
+    }
+    pfree(desctuple);
+
+  }
+
+  heap_close(description, RowExclusiveLock);
+
+}
+
+/*------------------------------------------------------------------    
+ * DeleteComments --
+ *
+ * This routine is used to purge any comments 
+ * associated with the Oid handed to this routine,
+ * regardless of the actual object type. It is
+ * called, for example, when a relation is destroyed.
+ *------------------------------------------------------------------
+ */
+
+void DeleteComments(Oid oid) {
+
+  Relation description;
+  TupleDesc tupDesc;
+  ScanKeyData entry;
+  HeapScanDesc scan;
+  HeapTuple searchtuple;
+
+  description = heap_openr(DescriptionRelationName, RowExclusiveLock);
+  tupDesc = description->rd_att;
+
+  /*** Now, open pg_description and attempt to find the old tuple ***/
+  
+  ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
+                        ObjectIdGetDatum(oid));
+  scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
+  searchtuple = heap_getnext(scan, 0);
+
+  /*** If a previous tuple exists, delete it ***/
+
+  if (HeapTupleIsValid(searchtuple)) {    
+    heap_delete(description, &searchtuple->t_self, NULL);
+  } 
+  
+  /*** Complete the scan, update indices, if necessary ***/
+
+  heap_endscan(scan);
+  heap_close(description, RowExclusiveLock);
+  
+}
+    
+/*------------------------------------------------------------------
+ * CommentRelation --
+ *
+ * This routine is used to add/drop a comment from a relation, where 
+ * a relation is a TABLE, SEQUENCE, VIEW or INDEX. The routine simply
+ * finds the relation name by searching the system cache, locating 
+ * the appropriate tuple, and inserting a comment using that 
+ * tuple's oid. Its parameters are the relation name and comments.
+ *------------------------------------------------------------------
+*/
+
+void CommentRelation(int reltype, char *relname, char *comment) {
+
+  HeapTuple reltuple;
+  Oid oid;
+  char relkind;
+
+  /*** First, check object security ***/
+
+  #ifndef NO_SECURITY
+  if (!pg_ownercheck(GetPgUserName(), relname, RELNAME)) {
+    elog(ERROR, "you are not permitted to comment on class '%s'", relname);
+  }
+  #endif
+
+  /*** Now, attempt to find the oid in the cached version of pg_class ***/
+
+  reltuple = SearchSysCacheTuple(RELNAME, PointerGetDatum(relname),
+                                0, 0, 0);
+  if (!HeapTupleIsValid(reltuple)) {
+    elog(ERROR, "relation '%s' does not exist", relname);
+  }
+
+  oid = reltuple->t_data->t_oid;
+
+  /*** Next, verify that the relation type matches the intent ***/
+
+  relkind = ((Form_pg_class) GETSTRUCT(reltuple))->relkind;
+
+  switch (reltype) {
+  case (INDEX):
+    if (relkind != 'i') {
+      elog(ERROR, "relation '%s' is not an index", relname);
+    }
+    break;
+  case (TABLE):
+    if (relkind != 'r') {
+      elog(ERROR, "relation '%s' is not a table", relname);
+    }
+    break;
+  case (VIEW):
+    if (relkind != 'r') {
+      elog(ERROR, "relation '%s' is not a view", relname);
+    }
+    break;
+  case (SEQUENCE):
+    if (relkind != 'S') {
+      elog(ERROR, "relation '%s' is not a sequence", relname);
+    }
+    break;
+  }
+    
+  /*** Create the comments using the tuple's oid ***/
+
+  CreateComments(oid, comment);  
+
+}
+
+/*------------------------------------------------------------------
+ * CommentAttribute --
+ *
+ * This routine is used to add/drop a comment from an attribute
+ * such as a table's column. The routine will check security 
+ * restrictions and then attempt to fetch the oid of the associated
+ * attribute. If successful, a comment is added/dropped, else an
+ * elog() exception is thrown.  The parameters are the relation
+ * and attribute names, and the comments 
+ *------------------------------------------------------------------
+*/
+
+void CommentAttribute(char *relname, char *attrname, char *comment) {
+
+  Relation relation;
+  HeapTuple attrtuple;
+  Oid oid;
+
+  /*** First, check object security ***/
+
+  #ifndef NO_SECURITY
+  if (!pg_ownercheck(GetPgUserName(), relname, RELNAME)) {
+    elog(ERROR, "you are not permitted to comment on class '%s\'", relname);
+  }
+  #endif
+  
+  /*** Now, fetch the attribute oid from the system cache ***/
+
+  relation = heap_openr(relname, AccessShareLock);  
+  attrtuple = SearchSysCacheTuple(ATTNAME, ObjectIdGetDatum(relation->rd_id),
+                                 PointerGetDatum(attrname), 0, 0);
+  if (!HeapTupleIsValid(attrtuple)) {
+    elog(ERROR, "'%s' is not an attribute of class '%s'",
+        attrname, relname);
+  }
+  oid = attrtuple->t_data->t_oid;
+  
+  /*** Call CreateComments() to create/drop the comments ***/
+
+  CreateComments(oid, comment);
+
+  /*** Now, close the heap relation and return ***/
+
+  heap_close(relation, AccessShareLock); 
+
+}
+
+/*------------------------------------------------------------------
+ * CommentDatabase --
+ *
+ * This routine is used to add/drop any user-comments a user might
+ * have regarding the specified database. The routine will check 
+ * security for owner permissions, and, if succesful, will then 
+ * attempt to find the oid of the database specified. Once found, 
+ * a comment is added/dropped using the CreateComments() routine. 
+ *------------------------------------------------------------------
+*/
+
+void CommentDatabase(char *database, char *comment) {
+
+  Relation pg_database;
+  HeapTuple dbtuple, usertuple;
+  ScanKeyData entry;
+  HeapScanDesc scan;
+  Oid oid;
+  bool superuser;
+  int4 dba, userid;
+  char *username;  
+
+  /*** First find the tuple in pg_database for the database ***/
+
+  pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
+  ScanKeyEntryInitialize(&entry, 0, Anum_pg_database_datname,
+                        F_NAMEEQ, NameGetDatum(database));
+  scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry);
+  dbtuple = heap_getnext(scan, 0);
+  
+  /*** Validate database exists, and fetch the dba id and oid ***/
+
+  if (!HeapTupleIsValid(dbtuple)) {
+    elog(ERROR, "database '%s' does not exist", database);
+  }
+  dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
+  oid = dbtuple->t_data->t_oid;
+  
+  /*** Now, fetch user information ***/
+  
+  username = GetPgUserName();
+  usertuple = SearchSysCacheTuple(USENAME, PointerGetDatum(username),
+                                 0, 0, 0);
+  if (!HeapTupleIsValid(usertuple)) {
+    elog(ERROR, "current user '%s' does not exist", username);
+  }
+  userid = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesysid;
+  superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
+  
+  /*** Allow if the userid matches the database dba or is a superuser ***/
+  
+  #ifndef NO_SECURITY
+  if (!(superuser || (userid == dba))) {
+    elog(ERROR, "you are not permitted to comment on database '%s'",
+        database);
+  }
+  #endif
+
+  /*** Create the comments with the pg_database oid ***/
+  
+  CreateComments(oid, comment);
+  
+  /*** Complete the scan and close any opened relations ***/
+  
+  heap_endscan(scan);
+  heap_close(pg_database, AccessShareLock);
+
+}
+
+/*------------------------------------------------------------------
+ * CommentRewrite --
+ *
+ * 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.
+ *------------------------------------------------------------------
+*/
+
+void CommentRewrite(char *rule, char *comment) {
+
+  HeapTuple rewritetuple;
+  Oid oid;
+  char *user, *relation;
+  int aclcheck;
+
+  /*** First, validate user ***/
+  
+  #ifndef NO_SECURITY  
+  user = GetPgUserName();
+  relation = RewriteGetRuleEventRel(rule);
+  aclcheck = pg_aclcheck(relation, user, ACL_RU);
+  if (aclcheck != ACLCHECK_OK) {
+    elog(ERROR, "you are not permitted to comment on rule '%s'",
+        rule);
+  }
+  #endif
+
+  /*** Next, find the rule's oid ***/
+  
+  rewritetuple = SearchSysCacheTuple(REWRITENAME, PointerGetDatum(rule),
+                                    0, 0, 0);
+  if (!HeapTupleIsValid(rewritetuple)) {
+    elog(ERROR, "rule '%s' does not exist", rule);
+  }
+
+  oid = rewritetuple->t_data->t_oid;
+  
+  /*** Call CreateComments() to create/drop the comments ***/
+
+  CreateComments(oid, comment);
+
+}
+
+/*------------------------------------------------------------------
+ * CommentType --
+ *
+ * This routine is used to add/drop any user-comments a user might
+ * have regarding a TYPE. The type is specified by name
+ * and, if found, and the user has appropriate permissions, a 
+ * comment will be added/dropped using the CreateComments() routine.
+ * The type's name and the comments are the paramters to this routine.
+ *------------------------------------------------------------------
+*/
+
+void CommentType(char *type, char *comment) {
+
+  HeapTuple typetuple;
+  Oid oid;
+  char *user;
+
+  /*** First, validate user ***/
+  
+  #ifndef NO_SECURITY  
+  user = GetPgUserName();
+  if (!pg_ownercheck(user, type, TYPNAME)) {    
+    elog(ERROR, "you are not permitted to comment on type '%s'",
+        type);
+  }
+  #endif
+
+  /*** Next, find the type's oid ***/
+  
+  typetuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(type),
+                                 0, 0, 0);
+  if (!HeapTupleIsValid(typetuple)) {
+    elog(ERROR, "type '%s' does not exist", type);
+  }
+
+  oid = typetuple->t_data->t_oid;
+  
+  /*** Call CreateComments() to create/drop the comments ***/
+
+  CreateComments(oid, comment);
+
+}
+
+/*------------------------------------------------------------------
+ * CommentAggregate --
+ *
+ * This routine is used to allow a user to provide comments on an 
+ * aggregate function. The aggregate function is determined by both
+ * its name and its argument type, which, with the comments are 
+ * the three parameters handed to this routine.
+ *------------------------------------------------------------------
+*/
+
+void CommentAggregate(char *aggregate, char *argument, char *comment) {
+  
+  HeapTuple aggtuple;
+  Oid baseoid, oid;
+  bool defined;
+  char *user;
+  
+  /*** First, attempt to determine the base aggregate oid ***/
+
+  if (argument) {
+    baseoid = TypeGet(argument, &defined);
+    if (!OidIsValid(baseoid)) {
+      elog(ERROR, "aggregate type '%s' does not exist", argument);
+    }
+  } else {
+    baseoid = 0;
+  }
+  
+  /*** Next, validate the user's attempt to comment ***/
+
+  #ifndef NO_SECURITY
+  user = GetPgUserName();
+  if (!pg_aggr_ownercheck(user, aggregate, baseoid)) {
+    if (argument) {
+      elog(ERROR, "you are not permitted to comment on aggregate '%s' %s '%s'",
+          aggregate, "with type", argument);
+    } else {
+      elog(ERROR, "you are not permitted to comment on aggregate '%s'",
+          aggregate);
+    }
+  }
+  #endif
+
+  /*** Now, attempt to find the actual tuple in pg_aggregate ***/
+
+  aggtuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggregate),
+                                ObjectIdGetDatum(baseoid), 0, 0);
+  if (!HeapTupleIsValid(aggtuple)) {
+    if (argument) {
+      elog(ERROR, "aggregate type '%s' does not exist for aggregate '%s'",
+          argument, aggregate);
+    } else {
+      elog(ERROR, "aggregate '%s' does not exist", aggregate);
+    }
+  }
+  
+  oid = aggtuple->t_data->t_oid;
+  
+  /*** Call CreateComments() to create/drop the comments ***/
+
+  CreateComments(oid, comment);
+
+}
+
+/*------------------------------------------------------------------
+ * CommentProc --
+ *
+ * This routine is used to allow a user to provide comments on an 
+ * procedure (function). The procedure is determined by both
+ * its name and its argument list. The argument list is expected to 
+ * be a series of parsed nodes pointed to by a List object. If the
+ * comments string is empty, the associated comment is dropped.
+ *------------------------------------------------------------------
+*/
+
+void CommentProc(char *function, List *arguments, char *comment) {
+
+  HeapTuple argtuple, functuple;
+  Oid oid, argoids[8];
+  char *user, *argument;
+  int i, argcount;
+
+  /*** First, initialize function's argument list with their type oids ***/
+
+  argcount = length(arguments);
+  if (argcount > 0) {
+    MemSet(argoids, 0, 8 * sizeof(Oid));
+    for (i = 0; i < argcount; i++) {
+      argument = strVal(lfirst(arguments));
+      arguments = lnext(arguments);
+      if (strcmp(argument, "opaque") == 0) {
+       argoids[i] = 0;
+      } else {
+       argtuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(argument),
+                                      0, 0, 0);
+       if (!HeapTupleIsValid(argtuple)) {
+         elog(ERROR, "function argument type '%s' does not exist",
+              argument);
+       }
+       argoids[i] = argtuple->t_data->t_oid;
+      }
+    }
+  }
+
+  /*** Now, validate the user's ability to comment on this function ***/
+
+  #ifndef NO_SECURITY
+  user = GetPgUserName();
+  if (!pg_func_ownercheck(user, function, argcount, argoids)) {
+    elog(ERROR, "you are not permitted to comment on function '%s'",
+        function);
+  }
+  #endif
+
+  /*** Now, find the corresponding oid for this procedure ***/
+
+  functuple = SearchSysCacheTuple(PRONAME, PointerGetDatum(function),
+                                 Int32GetDatum(argcount),
+                                 PointerGetDatum(argoids), 0);
+
+  /*** Deallocate our argument oids and check the function tuple ***/
+  
+  if (!HeapTupleIsValid(functuple)) {
+    elog(ERROR, "function '%s' with the supplied %s does not exist",
+        function, "argument list");
+  }
+    
+  oid = functuple->t_data->t_oid;
+  
+  /*** Call CreateComments() to create/drop the comments ***/
+
+  CreateComments(oid, comment);
+
+}
+  
+/*------------------------------------------------------------------
+ * CommentOperator --
+ *
+ * This routine is used to allow a user to provide comments on an 
+ * operator. The operator for commenting is determined by both
+ * its name and its argument list which defines the left and right
+ * hand types the operator will operate on. The argument list is 
+ * expected to be a couple of parse nodes pointed to be a List 
+ * object. If the comments string is empty, the associated comment 
+ * is dropped.
+ *------------------------------------------------------------------
+*/
+
+void CommentOperator(char *opername, List *arguments, char *comment) {
+
+  HeapTuple optuple;
+  Oid oid, leftoid = InvalidOid, rightoid = InvalidOid;
+  bool defined;
+  char oprtype = 0, *user, *lefttype = NULL, *righttype = NULL;
+
+  /*** Initialize our left and right argument types ***/
+
+  if (lfirst(arguments) != NULL) {
+    lefttype = strVal(lfirst(arguments));
+  }  
+  if (lsecond(arguments) != NULL) {
+    righttype = strVal(lsecond(arguments));
+  }
+
+  /*** Attempt to fetch the left oid, if specified ***/
+
+  if (lefttype != NULL) {
+    leftoid = TypeGet(lefttype, &defined);
+    if (!OidIsValid(leftoid)) {
+      elog(ERROR, "left type '%s' does not exist", lefttype);
+    }
+  }
+  
+  /*** Attempt to fetch the right oid, if specified ***/
+  
+  if (righttype != NULL) {
+    rightoid = TypeGet(righttype, &defined);
+    if (!OidIsValid(rightoid)) {
+      elog(ERROR, "right type '%s' does not exist", righttype);
+    }
+  }
+
+  /*** Determine operator type ***/
+
+  if (OidIsValid(leftoid) && (OidIsValid(rightoid))) oprtype = 'b';
+  else if (OidIsValid(leftoid)) oprtype = 'l';
+  else if (OidIsValid(rightoid)) oprtype = 'r';
+  else elog(ERROR, "operator '%s' is of an illegal type'", opername);
+  
+  /*** Attempt to fetch the operator oid ***/
+
+  optuple = SearchSysCacheTupleCopy(OPRNAME, PointerGetDatum(opername),
+                                   ObjectIdGetDatum(leftoid),
+                                   ObjectIdGetDatum(rightoid),
+                                   CharGetDatum(oprtype));
+  if (!HeapTupleIsValid(optuple)) {
+    elog(ERROR, "operator '%s' does not exist", opername);
+  }
+
+  oid = optuple->t_data->t_oid;  
+  
+  /*** Valid user's ability to comment on this operator ***/
+
+  #ifndef NO_SECURITY
+  user = GetPgUserName();
+  if (!pg_ownercheck(user, (char *) ObjectIdGetDatum(oid), OPROID)) {
+    elog(ERROR, "you are not permitted to comment on operator '%s'",
+        opername);
+  }
+  #endif
+
+  /*** Call CreateComments() to create/drop the comments ***/
+
+  CreateComments(oid, comment);
+
+}
+
+/*------------------------------------------------------------------
+ * CommentTrigger --
+ *
+ * This routine is used to allow a user to provide comments on a
+ * trigger event. The trigger for commenting is determined by both
+ * its name and the relation to which it refers. The arguments to this
+ * function are the trigger name, the relation name, and the comments
+ * to add/drop.
+ *------------------------------------------------------------------
+*/
+
+void CommentTrigger(char *trigger, char *relname, char *comment) {
+
+  Form_pg_trigger data;
+  Relation pg_trigger, relation;
+  HeapTuple triggertuple;
+  HeapScanDesc scan;
+  ScanKeyData entry;
+  Oid oid = InvalidOid;
+  char *user;
+  
+  /*** First, validate the user's action ***/  
+
+  #ifndef NO_SECURITY
+  user = GetPgUserName();
+  if (!pg_ownercheck(user, relname, RELNAME)) {
+    elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'",
+        trigger, "defined for relation", relname);
+  }
+  #endif
+
+  /*** Now, fetch the trigger oid from pg_trigger  ***/
+
+  relation = heap_openr(relname, AccessShareLock);  
+  pg_trigger = heap_openr(TriggerRelationName, AccessShareLock);
+  ScanKeyEntryInitialize(&entry, 0, Anum_pg_trigger_tgrelid,
+                        F_OIDEQ, RelationGetRelid(relation));  
+  scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 1, &entry);
+  triggertuple = heap_getnext(scan, 0);
+  while (HeapTupleIsValid(triggertuple)) {
+    data = (Form_pg_trigger) GETSTRUCT(triggertuple);
+    if (namestrcmp(&(data->tgname), trigger) == 0) {
+      oid = triggertuple->t_data->t_oid;
+      break;
+    }
+    triggertuple = heap_getnext(scan, 0);
+  }
+
+  /*** If no trigger exists for the relation specified, notify user ***/
+
+  if (oid == InvalidOid) {
+    elog(ERROR, "trigger '%s' defined for relation '%s' does not exist",
+        trigger, relname);
+  }
+
+  /*** Create the comments with the pg_trigger oid ***/
+  
+  CreateComments(oid, comment);
+  
+  /*** Complete the scan and close any opened relations ***/
+  
+  heap_endscan(scan);
+  heap_close(pg_trigger, AccessShareLock);
+  heap_close(relation, AccessShareLock);
+
+}
index 9463d55a6a16be2bb64081d660bf97a5cdc90ed0..f07586dac0acaef18f8365eb03ee654ba7d11915 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.49 1999/10/15 01:49:39 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.50 1999/10/26 03:12:34 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -234,52 +234,6 @@ TruncateRelation(char *name)
        heap_truncate(name);
 }
 
-/*------------------------------------------------------------------
- * CommentRelation --
- *                Adds a comment to pg_description for the associated
- *                relation or relation attribute.
- *
- * Note:           
- *                The comment is dropped on the relation or attribute if
- *                the comment is an empty string.
- *------------------------------------------------------------------
- */
-void 
-CommentRelation(char *relname, char *attrname, char *comments) 
-{
-
-  Relation relation;
-  HeapTuple attrtuple;
-  Oid oid;
-
-  /*** First ensure relname is valid ***/
-
-  relation = heap_openr(relname, AccessShareLock);
-  
-  /*** Now, if an attribute was specified, fetch its oid, else use relation's oid ***/
-  
-  if (attrname != NULL) {
-    attrtuple = SearchSysCacheTuple(ATTNAME, ObjectIdGetDatum(relation->rd_id),
-                                   PointerGetDatum(attrname), 0, 0);
-    if (!HeapTupleIsValid(attrtuple)) {
-      elog(ERROR, "CommentRelation: attribute \"%s\" is not an attribute of relation \"%s\"",
-          attrname, relname);
-    }
-    oid = attrtuple->t_data->t_oid;
-  } else {
-    oid = RelationGetRelid(relation);
-  }
-  
-  /*** Call CreateComments() to create/drop the comments ***/
-
-  CreateComments(oid, comments);
-
-  /*** Now, close the heap relation ***/
-
-  heap_close(relation, AccessShareLock); 
-
-}
-
 /*
  * MergeAttributes
  *             Returns new schema given initial schema and supers.
index 75a917092a002054e3b3dca073bfe8e55b34f449..fc3bff2e4f4bc888db906e86c8ee639dd9fd09dc 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.42 1999/10/25 03:07:43 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.43 1999/10/26 03:12:34 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "catalog/catname.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_shadow.h"
+#include "commands/comment.h"
 #include "commands/dbcommands.h"
 #include "miscadmin.h"
 #include "storage/sinval.h"
@@ -149,6 +150,10 @@ destroydb(char *dbname, CommandDest dest)
                         dbname, db_id);
        }
 
+       /*** Delete any comments associated with the database ***/
+       
+       DeleteComments(db_id);
+
        /*
         * Houston, we have launch commit...
         *
index a73964cb02c3b1908afa842afdb31865b667c13b..67cd5c8c2abbd610bb61212b9d2ecb15607211c6 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.37 1999/09/18 19:06:40 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.38 1999/10/26 03:12:34 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
+#include "commands/comment.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
 #include "parser/parse_func.h"
@@ -93,7 +94,14 @@ RemoveOperator(char *operatorName,           /* operator name */
                        elog(ERROR, "RemoveOperator: operator '%s': permission denied",
                                 operatorName);
 #endif
+
+
+               /*** Delete any comments associated with this operator ***/
+
+               DeleteComments(tup->t_data->t_oid);
+
                heap_delete(relation, &tup->t_self, NULL);
+
        }
        else
        {
@@ -147,8 +155,17 @@ SingleOpOperatorRemove(Oid typeOid)
        {
                key[0].sk_attno = attnums[i];
                scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
-               while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
-                       heap_delete(rel, &tup->t_self, NULL);
+               while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) {
+
+                 /*** This is apparently a routine not in use, but remove ***/
+                 /*** any comments anyways ***/
+
+                 DeleteComments(tup->t_data->t_oid);
+
+                 heap_delete(rel, &tup->t_self, NULL);
+                 
+               }
+
                heap_endscan(scan);
        }
        heap_close(rel, RowExclusiveLock);
@@ -259,6 +276,11 @@ RemoveType(char *typeName)         /* type name to be removed */
        }
 
        typeOid = tup->t_data->t_oid;
+
+       /*** Delete any comments associated with this type ***/
+
+       DeleteComments(typeOid);
+
        heap_delete(relation, &tup->t_self, NULL);
 
        /* Now, Delete the "array of" that type */
@@ -347,6 +369,10 @@ RemoveFunction(char *functionName,         /* function name to be removed */
                elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
        }
 
+       /*** Delete any comments associated with this function ***/
+
+       DeleteComments(tup->t_data->t_oid);
+
        heap_delete(relation, &tup->t_self, NULL);
 
        heap_close(relation, RowExclusiveLock);
@@ -418,6 +444,11 @@ RemoveAggregate(char *aggName, char *aggType)
                                 aggName);
                }
        }
+       
+       /*** Remove any comments related to this aggregate ***/
+
+       DeleteComments(tup->t_data->t_oid);
+
        heap_delete(relation, &tup->t_self, NULL);
 
        heap_close(relation, RowExclusiveLock);
index 17a26c3c8e937b70d409158aa093c0995974c307..1bec6aa7626e91d660ac27498e3e17e0e9445e88 100644 (file)
@@ -16,6 +16,7 @@
 #include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_trigger.h"
+#include "commands/comment.h"
 #include "commands/trigger.h"
 #include "executor/executor.h"
 #include "miscadmin.h"
@@ -297,8 +298,14 @@ DropTrigger(DropTrigStmt *stmt)
 
                if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
                {
-                       heap_delete(tgrel, &tuple->t_self, NULL);
-                       tgfound++;
+
+                 /*** Delete any comments associated with this trigger ***/
+
+                 DeleteComments(tuple->t_data->t_oid);
+
+                 heap_delete(tgrel, &tuple->t_self, NULL);
+                 tgfound++;
+                 
                }
                else
                        found++;
@@ -355,8 +362,15 @@ RelationRemoveTriggers(Relation rel)
 
        tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
 
-       while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
-               heap_delete(tgrel, &tup->t_self, NULL);
+       while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0))) {
+
+         /*** Delete any comments associated with this trigger ***/
+
+         DeleteComments(tup->t_data->t_oid);
+         
+         heap_delete(tgrel, &tup->t_self, NULL);
+
+       }
 
        heap_endscan(tgscan);
 
index 16a4efa2baa49fdeb6babe428db091e2cda13e76..a4a0c721ea318ae884ae6aeb682a7a3d7ab50d40 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.109 1999/10/15 01:49:41 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.110 1999/10/26 03:12:34 momjian Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -196,7 +196,8 @@ Oid param_type(int t); /* used in parse_expr.c */
 %type <boolean> opt_cursor
 
 %type <ival>   copy_dirn, def_type, opt_direction, remove_type,
-                               opt_column, event
+               opt_column, event, comment_type, comment_cl,
+               comment_ag, comment_fn, comment_op, comment_tg
 
 %type <ival>   fetch_how_many
 
@@ -1542,28 +1543,101 @@ TruncateStmt:  TRUNCATE TABLE relation_name
 
 /*****************************************************************************
  *
- *             QUERY:
- *                     comment on [ table <relname> | column <relname>.<attribute> ]
- *                                is 'text'
+ *  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 | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] 
+ *               <objname> | AGGREGATE <aggname> <aggtype> | FUNCTION 
+ *              <funcname> (arg1, arg2, ...) | OPERATOR <op> 
+ *              (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
+ *              <relname> ] IS 'text'
  *
  *****************************************************************************/
  
-CommentStmt:   COMMENT ON COLUMN relation_name '.' attr_name IS Sconst
+CommentStmt:   COMMENT ON comment_type name IS Sconst
+                       {
+                               CommentStmt *n = makeNode(CommentStmt);
+                               n->objtype = $3;
+                               n->objname = $4;
+                               n->objproperty = NULL;
+                               n->objlist = NULL;
+                               n->comment = $6;
+                               $$ = (Node *) n;
+                       }
+               | COMMENT ON comment_cl relation_name '.' attr_name IS Sconst
                        {
                                CommentStmt *n = makeNode(CommentStmt);
-                               n->relname = $4;
-                               n->attrname = $6;
+                               n->objtype = $3;
+                               n->objname = $4;
+                               n->objproperty = $6;
+                               n->objlist = NULL;
                                n->comment = $8;
                                $$ = (Node *) n;
                        }
-               | COMMENT ON TABLE relation_name IS Sconst
-                       {
+               | COMMENT ON comment_ag name aggr_argtype IS Sconst
+                       {
                                CommentStmt *n = makeNode(CommentStmt);
-                               n->relname = $4;
-                               n->attrname = NULL;
-                               n->comment = $6;
+                               n->objtype = $3;
+                               n->objname = $4;
+                               n->objproperty = $5;
+                               n->objlist = NULL;
+                               n->comment = $7;
+                               $$ = (Node *) n;
+                       }
+               | COMMENT ON comment_fn func_name func_args IS Sconst
+                       {
+                               CommentStmt *n = makeNode(CommentStmt);
+                               n->objtype = $3;
+                               n->objname = $4;
+                               n->objproperty = NULL;
+                               n->objlist = $5;
+                               n->comment = $7;
+                               $$ = (Node *) n;
+                       }
+               | COMMENT ON comment_op all_Op '(' oper_argtypes ')' IS Sconst
+                       {
+                               CommentStmt *n = makeNode(CommentStmt);
+                               n->objtype = $3;
+                               n->objname = $4;
+                               n->objproperty = NULL;
+                               n->objlist = $6;
+                               n->comment = $9;
                                $$ = (Node *) n;
                        }
+               | COMMENT ON comment_tg name ON relation_name IS Sconst
+                       {
+                               CommentStmt *n = makeNode(CommentStmt);
+                               n->objtype = $3;
+                               n->objname = $4;
+                               n->objproperty = $6;
+                               n->objlist = NULL;
+                               n->comment = $8;
+                               $$ = (Node *) n;
+                       }
+               ;
+
+comment_type:  DATABASE { $$ = DATABASE; }
+               | INDEX { $$ = INDEX; }
+               | RULE { $$ = RULE; }
+               | SEQUENCE { $$ = SEQUENCE; }
+               | TABLE { $$ = TABLE; }
+               | TYPE_P { $$ = TYPE_P; }
+               | VIEW { $$ = VIEW; }
+               ;               
+
+comment_cl:    COLUMN { $$ = COLUMN; }
+               ;
+
+comment_ag:    AGGREGATE { $$ = AGGREGATE; }
+               ;
+
+comment_fn:    FUNCTION { $$ = FUNCTION; }
+               ;
+
+comment_op:    OPERATOR { $$ = OPERATOR; }
+               ;
+
+comment_tg:    TRIGGER { $$ = TRIGGER; }
                ;
 
 /*****************************************************************************
index 50e6c62c027beac0af47d36a97574e7bcfeb955f..c751550e494cd62a907485fa2bf09b63c1e1247b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.29 1999/09/18 19:07:19 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.30 1999/10/26 03:12:35 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/pg_rewrite.h"
+#include "commands/comment.h"
 #include "rewrite/rewriteRemove.h"
 #include "rewrite/rewriteSupport.h"
 #include "utils/syscache.h"
@@ -119,6 +120,13 @@ RemoveRewriteRule(char *ruleName)
         */
        prs2_deleteFromRelation(eventRelationOid, ruleId);
 
+       /*
+        * Delete any comments associated with this rule
+        *
+        */      
+        
+       DeleteComments(ruleId);
+
        /*
         * Now delete the tuple...
         */
@@ -158,8 +166,15 @@ RelationRemoveRules(Oid relid)
        scanDesc = heap_beginscan(RewriteRelation,
                                                          0, SnapshotNow, 1, &scanKeyData);
 
-       while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
-               heap_delete(RewriteRelation, &tuple->t_self, NULL);
+       while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0))) {
+
+         /*** Delete any comments associated with this relation ***/
+
+         DeleteComments(tuple->t_data->t_oid);
+          
+         heap_delete(RewriteRelation, &tuple->t_self, NULL);
+
+       }
 
        heap_endscan(scanDesc);
        heap_close(RewriteRelation, RowExclusiveLock);
index ec617d753692251b224e358014d3e504aab31ee0..6035c89b2eaf729a7336717219ad34b39fe5e9d5 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.70 1999/10/15 01:49:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.71 1999/10/26 03:12:36 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "commands/async.h"
 #include "commands/cluster.h"
 #include "commands/command.h"
+#include "commands/comment.h"
 #include "commands/copy.h"
 #include "commands/creatinh.h"
 #include "commands/dbcommands.h"
@@ -38,7 +39,6 @@
 #include "rewrite/rewriteRemove.h"
 #include "tcop/utility.h"
 #include "utils/acl.h"
-#include "utils/acl.h"
 #include "utils/ps_status.h"
 #include "utils/syscache.h"
 
@@ -242,14 +242,9 @@ ProcessUtility(Node *parsetree,
            
            PS_SET_STATUS(commandTag = "COMMENT");
            CHECK_IF_ABORTED();
-
-#ifndef NO_SECURITY
-           if (!pg_ownercheck(userName, statement->relname, RELNAME))
-             elog(ERROR, "you do not own class \"%s\"", statement->relname);
-#endif
-
-           CommentRelation(statement->relname, statement->attrname, 
-                           statement->comment);
+           CommentObject(statement->objtype, statement->objname,
+                         statement->objproperty, statement->objlist,
+                         statement->comment);
          }
          break;
            
index 4720013160486ad5f28023fac2d2cd19e817d8f7..1cb86b501c7584a4f50768b89a1187f0541ae271 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heap.h,v 1.23 1999/10/15 01:49:44 momjian Exp $
+ * $Id: heap.h,v 1.24 1999/10/26 03:12:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,23 +21,20 @@ typedef struct RawColumnDefault
        Node       *raw_default;        /* default value (untransformed parse tree) */
 } RawColumnDefault;
 
-extern Oid     RelnameFindRelid(char *relname);
+extern Oid RelnameFindRelid(char *relname);
 extern Relation heap_create(char *relname, TupleDesc att,
-                       bool isnoname, bool istemp);
+                           bool isnoname, bool istemp);
 
-extern Oid heap_create_with_catalog(char *relname,
-                                                TupleDesc tupdesc, char relkind, bool istemp);
+extern Oid heap_create_with_catalog(char *relname, TupleDesc tupdesc, 
+                                   char relkind, bool istemp);
 
 extern void heap_destroy_with_catalog(char *relname);
 extern void heap_truncate(char *relname);
 extern void heap_destroy(Relation rel);
 
-extern void CreateComments(Oid object, char *comments);
-extern void DeleteComments(Oid object);
-
 extern void AddRelationRawConstraints(Relation rel,
-                                                                         List *rawColDefaults,
-                                                                         List *rawConstraints);
+                                     List *rawColDefaults,
+                                     List *rawConstraints);
 
 extern void InitNoNameRelList(void);
 extern void DestroyNoNameRels(void);
diff --git a/src/include/commands/comment.h b/src/include/commands/comment.h
new file mode 100644 (file)
index 0000000..93ed200
--- /dev/null
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * comment.h
+ *       
+ * Prototypes for functions in commands/comment.c
+ *
+ * Copyright (c) 1999, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef COMMENT_H
+#define COMMENT_H
+
+/*------------------------------------------------------------------
+ * Function Prototypes --
+ * 
+ * The following protoypes define the public functions of the comment
+ * related routines. CreateComments() is used to create/drop a comment
+ * for any object with a valid oid. DeleteComments() deletes, if any, 
+ * the comments associated with the object. CommentObject() is used to 
+ * create comments to be identified by the specific type.
+ *------------------------------------------------------------------
+ */
+
+void CreateComments(Oid oid, char *comment);
+void DeleteComments(Oid oid);
+void CommentObject(int objtype, char *objname, char *objproperty, 
+                  List *objlist, char *comment);
+
+#endif  /* COMMENT_H */
index 11d5fdb7a0d41602c310cf8ff043f8ee6947dba0..8bfe142a1f499e74b7938b87c3feb85c16fdc310 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: creatinh.h,v 1.11 1999/10/15 01:49:46 momjian Exp $
+ * $Id: creatinh.h,v 1.12 1999/10/26 03:12:38 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,5 @@
 extern void DefineRelation(CreateStmt *stmt, char relkind);
 extern void RemoveRelation(char *name);
 extern void TruncateRelation(char *name);
-extern void CommentRelation(char *name, char *attr, char *comment);
 
 #endif  /* CREATINH_H */
index 208b31d740da7ac5b67b28b8be0d33f098514903..aac3ef7de536145ee05cefb9acab2d2a514c8311 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.85 1999/10/15 01:49:47 momjian Exp $
+ * $Id: parsenodes.h,v 1.86 1999/10/26 03:12:39 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -316,10 +316,12 @@ typedef struct TruncateStmt
  */
 typedef struct CommentStmt
 {
-  NodeTag         type;
-  char *relname;                       /* relation to create/drop comment */
-  char *attrname;                      /* attribute to comment on */
-  char *comment;                       /* the actual comment */
+  NodeTag type;
+  int objtype;                         /* Object's type */
+  char *objname;                       /* Name of the object */
+  char *objproperty;                   /* Property Id (such as column) */
+  List *objlist;                       /* Arguments for VAL objects */
+  char *comment;                       /* The comment to insert */
 } CommentStmt;
       
 /* ----------------------