aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/catalog/heap.c148
-rw-r--r--src/backend/catalog/index.c10
-rw-r--r--src/backend/commands/Makefile10
-rw-r--r--src/backend/commands/comment.c796
-rw-r--r--src/backend/commands/creatinh.c48
-rw-r--r--src/backend/commands/dbcommands.c7
-rw-r--r--src/backend/commands/remove.c37
-rw-r--r--src/backend/commands/trigger.c22
-rw-r--r--src/backend/parser/gram.y100
-rw-r--r--src/backend/rewrite/rewriteRemove.c21
-rw-r--r--src/backend/tcop/utility.c15
-rw-r--r--src/include/catalog/heap.h17
-rw-r--r--src/include/commands/comment.h31
-rw-r--r--src/include/commands/creatinh.h3
-rw-r--r--src/include/nodes/parsenodes.h12
15 files changed, 1039 insertions, 238 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index bd0a8668d0f..eb934f6d3d9 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -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);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index f8c4dac95e7..9e7850f8f63 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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"
@@ -1128,6 +1129,13 @@ index_destroy(Oid indexId)
elog(NOTICE, "Caution: DROP INDEX cannot be rolled back, so don't abort now");
/* ----------------
+ * fix DESCRIPTION relation
+ * ----------------
+ */
+
+ DeleteComments(indexId);
+
+ /* ----------------
* fix RELATION relation
* ----------------
*/
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index 3b4d3a8d317..fa1c4495e59 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -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
index 00000000000..c2dacaa8483
--- /dev/null
+++ b/src/backend/commands/comment.c
@@ -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);
+
+}
diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c
index 9463d55a6a1..f07586dac0a 100644
--- a/src/backend/commands/creatinh.c
+++ b/src/backend/commands/creatinh.c
@@ -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.
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 75a917092a0..fc3bff2e4f4 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -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...
*
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index a73964cb02c..67cd5c8c2ab 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -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);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 17a26c3c8e9..1bec6aa7626 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -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);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 16a4efa2baa..a4a0c721ea3 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -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; }
;
/*****************************************************************************
diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c
index 50e6c62c027..c751550e494 100644
--- a/src/backend/rewrite/rewriteRemove.c
+++ b/src/backend/rewrite/rewriteRemove.c
@@ -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"
@@ -120,6 +121,13 @@ RemoveRewriteRule(char *ruleName)
prs2_deleteFromRelation(eventRelationOid, ruleId);
/*
+ * Delete any comments associated with this rule
+ *
+ */
+
+ DeleteComments(ruleId);
+
+ /*
* Now delete the tuple...
*/
heap_delete(RewriteRelation, &tuple->t_self, NULL);
@@ -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);
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index ec617d75369..6035c89b2ea 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -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;
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index 47200131604..1cb86b501c7 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -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
index 00000000000..93ed200a74a
--- /dev/null
+++ b/src/include/commands/comment.h
@@ -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 */
diff --git a/src/include/commands/creatinh.h b/src/include/commands/creatinh.h
index 11d5fdb7a0d..8bfe142a1f4 100644
--- a/src/include/commands/creatinh.h
+++ b/src/include/commands/creatinh.h
@@ -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 */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 208b31d740d..aac3ef7de53 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -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;
/* ----------------------