diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-04-09 20:35:55 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-04-09 20:35:55 +0000 |
commit | f2d70d32ebd6c38d4fe93c1a684f5f29e5e76938 (patch) | |
tree | 5d041018177cdf6e9ca3ef0cc2eafac580a5bb0b /src/backend/commands/comment.c | |
parent | c419c224142eb4bbf6e9a47d2d3626f212fda0fc (diff) | |
download | postgresql-f2d70d32ebd6c38d4fe93c1a684f5f29e5e76938.tar.gz postgresql-f2d70d32ebd6c38d4fe93c1a684f5f29e5e76938.zip |
Functions live in namespaces. Qualified function names work, eg
SELECT schema1.func2(...). Aggregate names can be qualified at the
syntactic level, but the qualification is ignored for the moment.
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; |