diff options
Diffstat (limited to 'src/backend/commands/comment.c')
-rw-r--r-- | src/backend/commands/comment.c | 314 |
1 files changed, 141 insertions, 173 deletions
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index f8e5bc6fc6f..b7d57f6cce5 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1999-2001, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.38 2002/03/29 19:06:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.39 2002/04/09 20:35:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,7 @@ #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" +#include "catalog/namespace.h" #include "catalog/pg_database.h" #include "catalog/pg_description.h" #include "catalog/pg_namespace.h" @@ -40,87 +41,74 @@ #include "utils/syscache.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 * schemaname, char *relation, - char *comment); -static void CommentAttribute(char * schemaname, 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, List *arguments, 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 *schemaname, char *relation, - char *comments); - - -/*------------------------------------------------------------------ +static void CommentRelation(int objtype, List *relname, char *comment); +static void CommentAttribute(List *qualname, char *comment); +static void CommentDatabase(List *qualname, char *comment); +static void CommentRule(List *qualname, char *comment); +static void CommentType(List *typename, char *comment); +static void CommentAggregate(List *aggregate, List *arguments, char *comment); +static void CommentProc(List *function, List *arguments, char *comment); +static void CommentOperator(List *qualname, List *arguments, char *comment); +static void CommentTrigger(List *qualname, char *comment); + + +/* * 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 comment string is - * empty, CreateComments() will drop any comments associated with - * the object. - *------------------------------------------------------------------ -*/ - + * pg_description for the object specified by the given SQL command. + */ void -CommentObject(int objtype, char *schemaname, char *objname, char *objproperty, - List *objlist, char *comment) +CommentObject(CommentStmt *stmt) { - switch (objtype) + switch (stmt->objtype) { case INDEX: case SEQUENCE: case TABLE: case VIEW: - CommentRelation(objtype, schemaname, objname, comment); + CommentRelation(stmt->objtype, stmt->objname, stmt->comment); break; case COLUMN: - CommentAttribute(schemaname, objname, objproperty, comment); + CommentAttribute(stmt->objname, stmt->comment); break; case DATABASE: - CommentDatabase(objname, comment); + CommentDatabase(stmt->objname, stmt->comment); break; case RULE: - CommentRewrite(objname, comment); + CommentRule(stmt->objname, stmt->comment); break; case TYPE_P: - CommentType(objname, comment); + CommentType(stmt->objname, stmt->comment); break; case AGGREGATE: - CommentAggregate(objname, objlist, comment); + CommentAggregate(stmt->objname, stmt->objargs, stmt->comment); break; case FUNCTION: - CommentProc(objname, objlist, comment); + CommentProc(stmt->objname, stmt->objargs, stmt->comment); break; case OPERATOR: - CommentOperator(objname, objlist, comment); + CommentOperator(stmt->objname, stmt->objargs, stmt->comment); break; case TRIGGER: - CommentTrigger(objname, schemaname, objproperty, comment); + CommentTrigger(stmt->objname, stmt->comment); break; default: elog(ERROR, "An attempt was made to comment on a unknown type: %d", - objtype); + stmt->objtype); } } -/*------------------------------------------------------------------ +/* * CreateComments -- * * Create a comment for the specified object descriptor. Inserts a new @@ -128,9 +116,7 @@ CommentObject(int objtype, char *schemaname, char *objname, char *objproperty, * * If the comment given is null or an empty string, instead delete any * existing comment for the specified key. - *------------------------------------------------------------------ */ - void CreateComments(Oid oid, Oid classoid, int32 subid, char *comment) { @@ -254,15 +240,13 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment) heap_close(description, NoLock); } -/*------------------------------------------------------------------ +/* * DeleteComments -- * * This routine is used to purge all comments associated with an object, * regardless of their objsubid. It is called, for example, when a relation * is destroyed. - *------------------------------------------------------------------ */ - void DeleteComments(Oid oid, Oid classoid) { @@ -316,7 +300,7 @@ DeleteComments(Oid oid, Oid classoid) heap_close(description, NoLock); } -/*------------------------------------------------------------------ +/* * CommentRelation -- * * This routine is used to add/drop a comment from a relation, where @@ -324,20 +308,14 @@ DeleteComments(Oid oid, Oid classoid) * 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. - *------------------------------------------------------------------ */ - static void -CommentRelation(int reltype, char *schemaname, char *relname, char *comment) +CommentRelation(int objtype, List *relname, char *comment) { Relation relation; - RangeVar *tgtrel = makeNode(RangeVar); - - - tgtrel->relname = relname; - tgtrel->schemaname = schemaname; - /* FIXME SCHEMA: Can we add comments to temp relations? */ - tgtrel->istemp = false; + RangeVar *tgtrel; + + tgtrel = makeRangeVarFromNameList(relname); /* * Open the relation. We do this mainly to acquire a lock that @@ -349,27 +327,32 @@ CommentRelation(int reltype, char *schemaname, char *relname, char *comment) /* Check object security */ if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - elog(ERROR, "you are not permitted to comment on class '%s'", relname); + elog(ERROR, "you are not permitted to comment on class '%s'", + RelationGetRelationName(relation)); /* Next, verify that the relation type matches the intent */ - switch (reltype) + switch (objtype) { case INDEX: if (relation->rd_rel->relkind != RELKIND_INDEX) - elog(ERROR, "relation '%s' is not an index", relname); + elog(ERROR, "relation '%s' is not an index", + RelationGetRelationName(relation)); break; case TABLE: if (relation->rd_rel->relkind != RELKIND_RELATION) - elog(ERROR, "relation '%s' is not a table", relname); + elog(ERROR, "relation '%s' is not a table", + RelationGetRelationName(relation)); break; case VIEW: if (relation->rd_rel->relkind != RELKIND_VIEW) - elog(ERROR, "relation '%s' is not a view", relname); + elog(ERROR, "relation '%s' is not a view", + RelationGetRelationName(relation)); break; case SEQUENCE: if (relation->rd_rel->relkind != RELKIND_SEQUENCE) - elog(ERROR, "relation '%s' is not a sequence", relname); + elog(ERROR, "relation '%s' is not a sequence", + RelationGetRelationName(relation)); break; } @@ -381,7 +364,7 @@ CommentRelation(int reltype, char *schemaname, char *relname, char *comment) relation_close(relation, NoLock); } -/*------------------------------------------------------------------ +/* * CommentAttribute -- * * This routine is used to add/drop a comment from an attribute @@ -390,34 +373,40 @@ CommentRelation(int reltype, char *schemaname, char *relname, char *comment) * 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 - *------------------------------------------------------------------ -*/ - + */ static void -CommentAttribute(char *schemaname, char *relname, char *attrname, char *comment) +CommentAttribute(List *qualname, char *comment) { - RangeVar *rel = makeNode(RangeVar); + int nnames; + List *relname; + char *attrname; + RangeVar *rel; Relation relation; AttrNumber attnum; - /* Open the containing relation to ensure it won't go away meanwhile */ + /* Separate relname and attr name */ + nnames = length(qualname); + if (nnames < 2) + elog(ERROR, "CommentAttribute: must specify relation.attribute"); + relname = ltruncate(nnames-1, listCopy(qualname)); + attrname = strVal(nth(nnames-1, qualname)); - rel->relname = relname; - rel->schemaname = schemaname; - rel->istemp = false; + /* Open the containing relation to ensure it won't go away meanwhile */ + rel = makeRangeVarFromNameList(relname); relation = heap_openrv(rel, AccessShareLock); /* Check object security */ if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - elog(ERROR, "you are not permitted to comment on class '%s'", relname); + elog(ERROR, "you are not permitted to comment on class '%s'", + RelationGetRelationName(relation)); /* Now, fetch the attribute number from the system cache */ attnum = get_attnum(RelationGetRelid(relation), attrname); if (attnum == InvalidAttrNumber) elog(ERROR, "'%s' is not an attribute of class '%s'", - attrname, relname); + attrname, RelationGetRelationName(relation)); /* Create the comment using the relation's oid */ @@ -429,7 +418,7 @@ CommentAttribute(char *schemaname, char *relname, char *attrname, char *comment) heap_close(relation, NoLock); } -/*------------------------------------------------------------------ +/* * CommentDatabase -- * * This routine is used to add/drop any user-comments a user might @@ -437,23 +426,26 @@ CommentAttribute(char *schemaname, char *relname, char *attrname, char *comment) * 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. - *------------------------------------------------------------------ -*/ - + */ static void -CommentDatabase(char *database, char *comment) +CommentDatabase(List *qualname, char *comment) { + char *database; Relation pg_database; ScanKeyData entry; HeapScanDesc scan; HeapTuple dbtuple; Oid oid; + if (length(qualname) != 1) + elog(ERROR, "CommentDatabase: database name may not be qualified"); + database = strVal(lfirst(qualname)); + /* 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)); + F_NAMEEQ, CStringGetDatum(database)); scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry); dbtuple = heap_getnext(scan, 0); @@ -479,25 +471,29 @@ CommentDatabase(char *database, char *comment) heap_close(pg_database, AccessShareLock); } -/*------------------------------------------------------------------ - * CommentRewrite -- +/* + * CommentRule -- * * This routine is used to add/drop any user-comments a user might * have regarding a specified RULE. The rule is specified by name * and, if found, and the user has appropriate permissions, a * comment will be added/dropped using the CreateComments() routine. - *------------------------------------------------------------------ -*/ - + */ static void -CommentRewrite(char *rule, char *comment) +CommentRule(List *qualname, char *comment) { + char *rule; HeapTuple tuple; Oid reloid; Oid ruleoid; Oid classoid; int32 aclcheck; + /* XXX this is gonna change soon */ + if (length(qualname) != 1) + elog(ERROR, "CommentRule: rule name may not be qualified"); + rule = strVal(lfirst(qualname)); + /* Find the rule's pg_rewrite tuple, get its OID and its table's OID */ tuple = SearchSysCache(RULENAME, @@ -528,7 +524,7 @@ CommentRewrite(char *rule, char *comment) CreateComments(ruleoid, classoid, 0, comment); } -/*------------------------------------------------------------------ +/* * CommentType -- * * This routine is used to add/drop any user-comments a user might @@ -536,42 +532,43 @@ CommentRewrite(char *rule, char *comment) * 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. - *------------------------------------------------------------------ -*/ - + */ static void -CommentType(char *type, char *comment) +CommentType(List *typename, char *comment) { + TypeName *tname; Oid oid; + /* XXX a bit of a crock; should accept TypeName in COMMENT syntax */ + tname = makeNode(TypeName); + tname->names = typename; + tname->typmod = -1; + /* Find the type's oid */ - /* XXX WRONG: need to deal with qualified type names */ - oid = typenameTypeId(makeTypeName(type)); + oid = typenameTypeId(tname); /* Check object security */ if (!pg_type_ownercheck(oid, GetUserId())) - elog(ERROR, "you are not permitted to comment on type '%s'", - type); + elog(ERROR, "you are not permitted to comment on type %s", + TypeNameToString(tname)); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, RelOid_pg_type, 0, 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. - *------------------------------------------------------------------ -*/ - + */ static void -CommentAggregate(char *aggregate, List *arguments, char *comment) +CommentAggregate(List *aggregate, List *arguments, char *comment) { TypeName *aggtype = (TypeName *) lfirst(arguments); Oid baseoid, @@ -587,7 +584,7 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) /* Now, attempt to find the actual tuple in pg_aggregate */ oid = GetSysCacheOid(AGGNAME, - PointerGetDatum(aggregate), + PointerGetDatum(strVal(lfirst(aggregate))), /* XXX */ ObjectIdGetDatum(baseoid), 0, 0); if (!OidIsValid(oid)) @@ -598,11 +595,11 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) if (!pg_aggr_ownercheck(oid, GetUserId())) { if (baseoid == InvalidOid) - elog(ERROR, "you are not permitted to comment on aggregate '%s' for all types", - aggregate); + elog(ERROR, "you are not permitted to comment on aggregate %s for all types", + NameListToString(aggregate)); else - elog(ERROR, "you are not permitted to comment on aggregate '%s' for type %s", - aggregate, format_type_be(baseoid)); + elog(ERROR, "you are not permitted to comment on aggregate %s for type %s", + NameListToString(aggregate), format_type_be(baseoid)); } /* pg_aggregate doesn't have a hard-coded OID, so must look it up */ @@ -615,7 +612,7 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) CreateComments(oid, classoid, 0, comment); } -/*------------------------------------------------------------------ +/* * CommentProc -- * * This routine is used to allow a user to provide comments on an @@ -623,64 +620,29 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) * 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. - *------------------------------------------------------------------ -*/ - + */ static void -CommentProc(char *function, List *arguments, char *comment) +CommentProc(List *function, List *arguments, char *comment) { - Oid oid, - argoids[FUNC_MAX_ARGS]; - int i, - argcount; - - /* First, initialize function's argument list with their type oids */ - - MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid)); - argcount = length(arguments); - if (argcount > FUNC_MAX_ARGS) - elog(ERROR, "functions cannot have more than %d arguments", - FUNC_MAX_ARGS); - for (i = 0; i < argcount; i++) - { - TypeName *t = (TypeName *) lfirst(arguments); - - argoids[i] = LookupTypeName(t); - if (!OidIsValid(argoids[i])) - { - char *typnam = TypeNameToString(t); - - if (strcmp(typnam, "opaque") == 0) - argoids[i] = InvalidOid; - else - elog(ERROR, "Type \"%s\" does not exist", typnam); - } + Oid oid; - arguments = lnext(arguments); - } + /* Look up the procedure */ - /* Now, find the corresponding oid for this procedure */ - - oid = GetSysCacheOid(PROCNAME, - PointerGetDatum(function), - Int32GetDatum(argcount), - PointerGetDatum(argoids), - 0); - if (!OidIsValid(oid)) - func_error("CommentProc", function, argcount, argoids, NULL); + oid = LookupFuncNameTypeNames(function, arguments, + true, "CommentProc"); /* Now, validate the user's ability to comment on this function */ if (!pg_proc_ownercheck(oid, GetUserId())) - elog(ERROR, "you are not permitted to comment on function '%s'", - function); + elog(ERROR, "you are not permitted to comment on function %s", + NameListToString(function)); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, RelOid_pg_proc, 0, comment); } -/*------------------------------------------------------------------ +/* * CommentOperator -- * * This routine is used to allow a user to provide comments on an @@ -694,12 +656,11 @@ CommentProc(char *function, List *arguments, char *comment) * NOTE: we actually attach the comment to the procedure that underlies * the operator. This is a feature, not a bug: we want the same comment * to be visible for both operator and function. - *------------------------------------------------------------------ -*/ - + */ static void -CommentOperator(char *opername, List *arguments, char *comment) +CommentOperator(List *qualname, List *arguments, char *comment) { + char *opername = strVal(lfirst(qualname)); /* XXX */ TypeName *typenode1 = (TypeName *) lfirst(arguments); TypeName *typenode2 = (TypeName *) lsecond(arguments); char oprtype = 0; @@ -760,21 +721,22 @@ CommentOperator(char *opername, List *arguments, char *comment) CreateComments(oid, RelOid_pg_proc, 0, 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. - *------------------------------------------------------------------ -*/ - + * function are the trigger name and relation name (merged into a qualified + * name), and the comment to add/drop. + */ static void -CommentTrigger(char *trigger, char *schemaname, char *relname, char *comment) +CommentTrigger(List *qualname, char *comment) { - RangeVar *rel = makeNode(RangeVar); + int nnames; + List *relname; + char *trigname; + RangeVar *rel; Relation pg_trigger, relation; HeapTuple triggertuple; @@ -782,16 +744,22 @@ CommentTrigger(char *trigger, char *schemaname, char *relname, char *comment) ScanKeyData entry[2]; Oid oid; - /* First, validate the user's action */ + /* Separate relname and trig name */ + nnames = length(qualname); + if (nnames < 2) + elog(ERROR, "CommentTrigger: must specify relation and trigger"); + relname = ltruncate(nnames-1, listCopy(qualname)); + trigname = strVal(nth(nnames-1, qualname)); - rel->relname = relname; - rel->schemaname = schemaname; - rel->istemp = false; + /* Open the owning relation to ensure it won't go away meanwhile */ + rel = makeRangeVarFromNameList(relname); relation = heap_openrv(rel, AccessShareLock); + /* Check object security */ + if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'", - trigger, "defined for relation", relname); + elog(ERROR, "you are not permitted to comment on trigger '%s' for relation '%s'", + trigname, RelationGetRelationName(relation)); /* Fetch the trigger oid from pg_trigger */ @@ -801,15 +769,15 @@ CommentTrigger(char *trigger, char *schemaname, char *relname, char *comment) ObjectIdGetDatum(RelationGetRelid(relation))); ScanKeyEntryInitialize(&entry[1], 0x0, Anum_pg_trigger_tgname, F_NAMEEQ, - NameGetDatum(trigger)); + CStringGetDatum(trigname)); scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 2, entry); triggertuple = heap_getnext(scan, 0); /* If no trigger exists for the relation specified, notify user */ if (!HeapTupleIsValid(triggertuple)) - elog(ERROR, "trigger '%s' defined for relation '%s' does not exist", - trigger, relname); + elog(ERROR, "trigger '%s' for relation '%s' does not exist", + trigname, RelationGetRelationName(relation)); oid = triggertuple->t_data->t_oid; |