diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/Makefile | 10 | ||||
-rw-r--r-- | src/backend/commands/comment.c | 796 | ||||
-rw-r--r-- | src/backend/commands/creatinh.c | 48 | ||||
-rw-r--r-- | src/backend/commands/dbcommands.c | 7 | ||||
-rw-r--r-- | src/backend/commands/remove.c | 37 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 22 |
6 files changed, 863 insertions, 57 deletions
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); |