aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/comment.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/comment.c')
-rw-r--r--src/backend/commands/comment.c456
1 files changed, 256 insertions, 200 deletions
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 2f28130f8b9..4bf6993d02a 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,13 +7,14 @@
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.31 2001/06/25 21:11:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.32 2001/08/10 18:57:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
@@ -22,7 +23,6 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
-#include "catalog/pg_class.h"
#include "commands/comment.h"
#include "miscadmin.h"
#include "parser/parse_expr.h"
@@ -32,6 +32,7 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -54,7 +55,7 @@ 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 *relation, char *comments);
-static void CreateComments(Oid oid, char *comment);
+
/*------------------------------------------------------------------
* CommentObject --
@@ -64,7 +65,7 @@ static void CreateComments(Oid oid, char *comment);
* 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
+ * by calling the CreateComments() routine. If the comment string is
* empty, CreateComments() will drop any comments associated with
* the object.
*------------------------------------------------------------------
@@ -74,135 +75,158 @@ void
CommentObject(int objtype, char *objname, char *objproperty,
List *objlist, char *comment)
{
-
switch (objtype)
{
- case (INDEX):
- case (SEQUENCE):
- case (TABLE):
- case (VIEW):
+ case INDEX:
+ case SEQUENCE:
+ case TABLE:
+ case VIEW:
CommentRelation(objtype, objname, comment);
break;
- case (COLUMN):
+ case COLUMN:
CommentAttribute(objname, objproperty, comment);
break;
- case (DATABASE):
+ case DATABASE:
CommentDatabase(objname, comment);
break;
- case (RULE):
+ case RULE:
CommentRewrite(objname, comment);
break;
- case (TYPE_P):
+ case TYPE_P:
CommentType(objname, comment);
break;
- case (AGGREGATE):
+ case AGGREGATE:
CommentAggregate(objname, objlist, comment);
break;
- case (FUNCTION):
+ case FUNCTION:
CommentProc(objname, objlist, comment);
break;
- case (OPERATOR):
+ case OPERATOR:
CommentOperator(objname, objlist, comment);
break;
- case (TRIGGER):
+ case TRIGGER:
CommentTrigger(objname, objproperty, comment);
break;
default:
- elog(ERROR, "An attempt was made to comment on a unknown type: %i",
+ elog(ERROR, "An attempt was made to comment on a unknown type: %d",
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.
+ * Create a comment for the specified object descriptor. Inserts a new
+ * pg_description tuple, or replaces an existing one with the same key.
*
+ * If the comment given is null or an empty string, instead delete any
+ * existing comment for the specified key.
*------------------------------------------------------------------
*/
-static void
-CreateComments(Oid oid, char *comment)
+void
+CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
{
-
Relation description;
- TupleDesc tupDesc;
- HeapScanDesc scan;
- ScanKeyData entry;
- HeapTuple desctuple = NULL,
- searchtuple;
+ Relation descriptionindex;
+ ScanKeyData skey[3];
+ IndexScanDesc sd;
+ RetrieveIndexResult indexRes;
+ HeapTupleData oldtuple;
+ Buffer buffer;
+ HeapTuple newtuple = NULL;
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 ***/
+ /* Reduce empty-string to NULL case */
+ if (comment != NULL && strlen(comment) == 0)
+ comment = NULL;
- description = heap_openr(DescriptionRelationName, RowExclusiveLock);
- tupDesc = description->rd_att;
- if ((comment != NULL) && (strlen(comment) > 0))
+ /* Prepare to form or update a tuple, if necessary */
+ if (comment != NULL)
{
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++] = ObjectIdGetDatum(classoid);
+ values[i++] = Int32GetDatum(subid);
values[i++] = DirectFunctionCall1(textin, CStringGetDatum(comment));
}
- /*** Now, open pg_description and attempt to find the old tuple ***/
+ /* Open pg_description and its index */
- ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
+ description = heap_openr(DescriptionRelationName, RowExclusiveLock);
+ descriptionindex = index_openr(DescriptionObjIndex);
+
+ /* Use the index to search for a matching old tuple */
+
+ ScanKeyEntryInitialize(&skey[0],
+ (bits16) 0x0,
+ (AttrNumber) 1,
+ (RegProcedure) 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 ***/
+ ScanKeyEntryInitialize(&skey[1],
+ (bits16) 0x0,
+ (AttrNumber) 2,
+ (RegProcedure) F_OIDEQ,
+ ObjectIdGetDatum(classoid));
+
+ ScanKeyEntryInitialize(&skey[2],
+ (bits16) 0x0,
+ (AttrNumber) 3,
+ (RegProcedure) F_INT4EQ,
+ Int32GetDatum(subid));
+
+ sd = index_beginscan(descriptionindex, false, 3, skey);
- if (HeapTupleIsValid(searchtuple))
+ oldtuple.t_datamcxt = CurrentMemoryContext;
+ oldtuple.t_data = NULL;
+
+ while ((indexRes = index_getnext(sd, ForwardScanDirection)))
{
+ oldtuple.t_self = indexRes->heap_iptr;
+ heap_fetch(description, SnapshotNow, &oldtuple, &buffer, sd);
+ pfree(indexRes);
+
+ if (oldtuple.t_data == NULL)
+ continue; /* time qual failed */
- /*** If the comment is blank, delete old entry, else update it ***/
+ /* Found the old tuple, so delete or update it */
- if ((comment == NULL) || (strlen(comment) == 0))
- simple_heap_delete(description, &searchtuple->t_self);
+ if (comment == NULL)
+ simple_heap_delete(description, &oldtuple.t_self);
else
{
- desctuple = heap_modifytuple(searchtuple, description, values,
- nulls, replaces);
- simple_heap_update(description, &searchtuple->t_self, desctuple);
- modified = TRUE;
+ newtuple = heap_modifytuple(&oldtuple, description, values,
+ nulls, replaces);
+ simple_heap_update(description, &oldtuple.t_self, newtuple);
}
+ ReleaseBuffer(buffer);
+ break; /* Assume there can be only one match */
}
- else
- {
- /*** Only if comment is non-blank do we form a new tuple ***/
+ index_endscan(sd);
- if ((comment != NULL) && (strlen(comment) > 0))
- {
- desctuple = heap_formtuple(tupDesc, values, nulls);
- heap_insert(description, desctuple);
- modified = TRUE;
- }
+ /* If we didn't find an old tuple, insert a new one */
+ if (oldtuple.t_data == NULL && comment != NULL)
+ {
+ newtuple = heap_formtuple(RelationGetDescr(description),
+ values, nulls);
+ heap_insert(description, newtuple);
}
- /*** Complete the scan, update indices, if necessary ***/
+ /* Update indexes, if necessary */
- heap_endscan(scan);
-
- if (modified)
+ if (newtuple != NULL)
{
if (RelationGetForm(description)->relhasindex)
{
@@ -211,57 +235,78 @@ CreateComments(Oid oid, char *comment)
CatalogOpenIndices(Num_pg_description_indices,
Name_pg_description_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_description_indices, description,
- desctuple);
+ newtuple);
CatalogCloseIndices(Num_pg_description_indices, idescs);
}
- heap_freetuple(desctuple);
-
+ heap_freetuple(newtuple);
}
- heap_close(description, RowExclusiveLock);
+ /* Done */
+ index_close(descriptionindex);
+ heap_close(description, NoLock);
}
/*------------------------------------------------------------------
* 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.
+ * 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)
+DeleteComments(Oid oid, Oid classoid)
{
-
Relation description;
- TupleDesc tupDesc;
- ScanKeyData entry;
- HeapScanDesc scan;
- HeapTuple searchtuple;
+ Relation descriptionindex;
+ ScanKeyData skey[2];
+ IndexScanDesc sd;
+ RetrieveIndexResult indexRes;
+ HeapTupleData oldtuple;
+ Buffer buffer;
+
+ /* Open pg_description and its index */
description = heap_openr(DescriptionRelationName, RowExclusiveLock);
- tupDesc = description->rd_att;
+ descriptionindex = index_openr(DescriptionObjIndex);
- /*** Now, open pg_description and attempt to find the old tuple ***/
+ /* Use the index to search for all matching old tuples */
- ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
+ ScanKeyEntryInitialize(&skey[0],
+ (bits16) 0x0,
+ (AttrNumber) 1,
+ (RegProcedure) F_OIDEQ,
ObjectIdGetDatum(oid));
- scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
- searchtuple = heap_getnext(scan, 0);
- /*** If a previous tuple exists, delete it ***/
+ ScanKeyEntryInitialize(&skey[1],
+ (bits16) 0x0,
+ (AttrNumber) 2,
+ (RegProcedure) F_OIDEQ,
+ ObjectIdGetDatum(classoid));
+
+ sd = index_beginscan(descriptionindex, false, 2, skey);
- if (HeapTupleIsValid(searchtuple))
- simple_heap_delete(description, &searchtuple->t_self);
+ while ((indexRes = index_getnext(sd, ForwardScanDirection)))
+ {
+ oldtuple.t_self = indexRes->heap_iptr;
+ heap_fetch(description, SnapshotNow, &oldtuple, &buffer, sd);
+ pfree(indexRes);
- /*** Complete the scan, update indices, if necessary ***/
+ if (oldtuple.t_data == NULL)
+ continue; /* time qual failed */
- heap_endscan(scan);
- heap_close(description, RowExclusiveLock);
+ simple_heap_delete(description, &oldtuple.t_self);
+
+ ReleaseBuffer(buffer);
+ }
+
+ /* Done */
+ index_endscan(sd);
+ index_close(descriptionindex);
+ heap_close(description, NoLock);
}
/*------------------------------------------------------------------
@@ -273,59 +318,65 @@ DeleteComments(Oid oid)
* 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 *relname, char *comment)
{
- HeapTuple reltuple;
- Oid oid;
- char relkind;
+ Relation relation;
- /*** First, check object security ***/
+ /* First, check object security */
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "you are not permitted to comment on class '%s'", relname);
- /*** Now, attempt to find the oid in the cached version of pg_class ***/
-
- reltuple = SearchSysCache(RELNAME,
- PointerGetDatum(relname),
- 0, 0, 0);
- if (!HeapTupleIsValid(reltuple))
- elog(ERROR, "relation '%s' does not exist", relname);
-
- oid = reltuple->t_data->t_oid;
-
- relkind = ((Form_pg_class) GETSTRUCT(reltuple))->relkind;
-
- ReleaseSysCache(reltuple);
+ /*
+ * Open the relation. We do this mainly to acquire a lock that ensures
+ * no one else drops the relation before we commit. (If they did, they'd
+ * fail to remove the entry we are about to make in pg_description.)
+ *
+ * heap_openr will complain if it's an index, so we must do this:
+ */
+ if (reltype != INDEX)
+ relation = heap_openr(relname, AccessShareLock);
+ else
+ {
+ relation = index_openr(relname);
+ LockRelation(relation, AccessShareLock);
+ }
- /*** Next, verify that the relation type matches the intent ***/
+ /* Next, verify that the relation type matches the intent */
switch (reltype)
{
- case (INDEX):
- if (relkind != RELKIND_INDEX)
+ case INDEX:
+ if (relation->rd_rel->relkind != RELKIND_INDEX)
elog(ERROR, "relation '%s' is not an index", relname);
break;
- case (TABLE):
- if (relkind != RELKIND_RELATION)
+ case TABLE:
+ if (relation->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "relation '%s' is not a table", relname);
break;
- case (VIEW):
- if (relkind != RELKIND_VIEW)
+ case VIEW:
+ if (relation->rd_rel->relkind != RELKIND_VIEW)
elog(ERROR, "relation '%s' is not a view", relname);
break;
- case (SEQUENCE):
- if (relkind != RELKIND_SEQUENCE)
+ case SEQUENCE:
+ if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
elog(ERROR, "relation '%s' is not a sequence", relname);
break;
}
- /*** Create the comments using the tuple's oid ***/
+ /* Create the comment using the relation's oid */
+
+ CreateComments(RelationGetRelid(relation), RelOid_pg_class, 0, comment);
- CreateComments(oid, comment);
+ /* Done, but hold lock until commit */
+
+ if (reltype != INDEX)
+ heap_close(relation, NoLock);
+ else
+ index_close(relation);
}
/*------------------------------------------------------------------
@@ -333,7 +384,7 @@ CommentRelation(int reltype, char *relname, char *comment)
*
* 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
+ * restrictions and then attempt to look up the specified
* 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
@@ -344,32 +395,30 @@ static void
CommentAttribute(char *relname, char *attrname, char *comment)
{
Relation relation;
- Oid oid;
+ AttrNumber attnum;
- /*** First, check object security ***/
+ /* First, check object security */
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
- elog(ERROR, "you are not permitted to comment on class '%s\'", relname);
+ elog(ERROR, "you are not permitted to comment on class '%s'", relname);
/* Open the containing relation to ensure it won't go away meanwhile */
relation = heap_openr(relname, AccessShareLock);
- /*** Now, fetch the attribute oid from the system cache ***/
+ /* Now, fetch the attribute number from the system cache */
- oid = GetSysCacheOid(ATTNAME,
- ObjectIdGetDatum(relation->rd_id),
- PointerGetDatum(attrname),
- 0, 0);
- if (!OidIsValid(oid))
+ attnum = get_attnum(RelationGetRelid(relation), attrname);
+ if (attnum == InvalidAttrNumber)
elog(ERROR, "'%s' is not an attribute of class '%s'",
attrname, relname);
- /*** Call CreateComments() to create/drop the comments ***/
+ /* Create the comment using the relation's oid */
- CreateComments(oid, comment);
+ CreateComments(RelationGetRelid(relation), RelOid_pg_class,
+ (int32) attnum, comment);
- /*** Now, close the heap relation and return ***/
+ /* Done, but hold lock until commit */
heap_close(relation, NoLock);
}
@@ -394,7 +443,7 @@ CommentDatabase(char *database, char *comment)
HeapTuple dbtuple;
Oid oid;
- /*** First find the tuple in pg_database for the database ***/
+ /* First find the tuple in pg_database for the database */
pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
ScanKeyEntryInitialize(&entry, 0, Anum_pg_database_datname,
@@ -402,23 +451,23 @@ CommentDatabase(char *database, char *comment)
scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry);
dbtuple = heap_getnext(scan, 0);
- /*** Validate database exists, and fetch the db oid ***/
+ /* Validate database exists, and fetch the db oid */
if (!HeapTupleIsValid(dbtuple))
elog(ERROR, "database '%s' does not exist", database);
oid = dbtuple->t_data->t_oid;
- /*** Allow if the user matches the database dba or is a superuser ***/
+ /* Allow if the user matches the database dba or is a superuser */
if (!(superuser() || is_dbadmin(oid)))
elog(ERROR, "you are not permitted to comment on database '%s'",
database);
- /*** Create the comments with the pg_database oid ***/
+ /* Create the comments with the pg_database oid */
- CreateComments(oid, comment);
+ CreateComments(oid, RelOid_pg_database, 0, comment);
- /*** Complete the scan and close any opened relations ***/
+ /* Complete the scan and close any opened relations */
heap_endscan(scan);
heap_close(pg_database, AccessShareLock);
@@ -438,22 +487,19 @@ static void
CommentRewrite(char *rule, char *comment)
{
Oid oid;
+ Oid classoid;
char *relation;
int aclcheck;
- /*** First, validate user ***/
+ /* First, validate user */
-#ifndef NO_SECURITY
relation = RewriteGetRuleEventRel(rule);
aclcheck = pg_aclcheck(relation, GetUserId(), ACL_RULE);
if (aclcheck != ACLCHECK_OK)
- {
elog(ERROR, "you are not permitted to comment on rule '%s'",
rule);
- }
-#endif
- /*** Next, find the rule's oid ***/
+ /* Next, find the rule's oid */
oid = GetSysCacheOid(RULENAME,
PointerGetDatum(rule),
@@ -461,9 +507,16 @@ CommentRewrite(char *rule, char *comment)
if (!OidIsValid(oid))
elog(ERROR, "rule '%s' does not exist", rule);
- /*** Call CreateComments() to create/drop the comments ***/
+ /* pg_rewrite doesn't have a hard-coded OID, so must look it up */
+
+ classoid = GetSysCacheOid(RELNAME,
+ PointerGetDatum(RewriteRelationName),
+ 0, 0, 0);
+ Assert(OidIsValid(classoid));
- CreateComments(oid, comment);
+ /* Call CreateComments() to create/drop the comments */
+
+ CreateComments(oid, classoid, 0, comment);
}
/*------------------------------------------------------------------
@@ -482,13 +535,13 @@ CommentType(char *type, char *comment)
{
Oid oid;
- /*** First, validate user ***/
+ /* First, validate user */
if (!pg_ownercheck(GetUserId(), type, TYPENAME))
elog(ERROR, "you are not permitted to comment on type '%s'",
type);
- /*** Next, find the type's oid ***/
+ /* Next, find the type's oid */
oid = GetSysCacheOid(TYPENAME,
PointerGetDatum(type),
@@ -496,9 +549,9 @@ CommentType(char *type, char *comment)
if (!OidIsValid(oid))
elog(ERROR, "type '%s' does not exist", type);
- /*** Call CreateComments() to create/drop the comments ***/
+ /* Call CreateComments() to create/drop the comments */
- CreateComments(oid, comment);
+ CreateComments(oid, RelOid_pg_type, 0, comment);
}
/*------------------------------------------------------------------
@@ -518,9 +571,10 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
char *aggtypename = NULL;
Oid baseoid,
oid;
+ Oid classoid;
bool defined;
- /*** First, attempt to determine the base aggregate oid ***/
+ /* First, attempt to determine the base aggregate oid */
if (aggtype)
{
@@ -530,21 +584,21 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
elog(ERROR, "type '%s' does not exist", aggtypename);
}
else
- baseoid = 0;
+ baseoid = InvalidOid;
- /*** Next, validate the user's attempt to comment ***/
+ /* Next, validate the user's attempt to comment */
if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid))
{
if (aggtypename)
- elog(ERROR, "you are not permitted to comment on aggregate '%s' %s '%s'",
- aggregate, "with type", aggtypename);
+ elog(ERROR, "you are not permitted to comment on aggregate '%s' with type '%s'",
+ aggregate, aggtypename);
else
elog(ERROR, "you are not permitted to comment on aggregate '%s'",
aggregate);
}
- /*** Now, attempt to find the actual tuple in pg_aggregate ***/
+ /* Now, attempt to find the actual tuple in pg_aggregate */
oid = GetSysCacheOid(AGGNAME,
PointerGetDatum(aggregate),
@@ -553,17 +607,22 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
if (!OidIsValid(oid))
{
if (aggtypename)
- {
elog(ERROR, "aggregate type '%s' does not exist for aggregate '%s'",
aggtypename, aggregate);
- }
else
elog(ERROR, "aggregate '%s' does not exist", aggregate);
}
- /*** Call CreateComments() to create/drop the comments ***/
+ /* pg_aggregate doesn't have a hard-coded OID, so must look it up */
+
+ classoid = GetSysCacheOid(RELNAME,
+ PointerGetDatum(AggregateRelationName),
+ 0, 0, 0);
+ Assert(OidIsValid(classoid));
- CreateComments(oid, comment);
+ /* Call CreateComments() to create/drop the comments */
+
+ CreateComments(oid, classoid, 0, comment);
}
/*------------------------------------------------------------------
@@ -585,7 +644,7 @@ CommentProc(char *function, List *arguments, char *comment)
int i,
argcount;
- /*** First, initialize function's argument list with their type oids ***/
+ /* First, initialize function's argument list with their type oids */
MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
argcount = length(arguments);
@@ -611,13 +670,13 @@ CommentProc(char *function, List *arguments, char *comment)
}
}
- /*** Now, validate the user's ability to comment on this function ***/
+ /* Now, validate the user's ability to comment on this function */
if (!pg_func_ownercheck(GetUserId(), function, argcount, argoids))
elog(ERROR, "you are not permitted to comment on function '%s'",
function);
- /*** Now, find the corresponding oid for this procedure ***/
+ /* Now, find the corresponding oid for this procedure */
oid = GetSysCacheOid(PROCNAME,
PointerGetDatum(function),
@@ -627,9 +686,9 @@ CommentProc(char *function, List *arguments, char *comment)
if (!OidIsValid(oid))
func_error("CommentProc", function, argcount, argoids, NULL);
- /*** Call CreateComments() to create/drop the comments ***/
+ /* Call CreateComments() to create/drop the comments */
- CreateComments(oid, comment);
+ CreateComments(oid, RelOid_pg_proc, 0, comment);
}
/*------------------------------------------------------------------
@@ -642,6 +701,10 @@ CommentProc(char *function, List *arguments, char *comment)
* 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.
+ *
+ * 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.
*------------------------------------------------------------------
*/
@@ -660,14 +723,14 @@ CommentOperator(char *opername, List *arguments, char *comment)
rightoid = InvalidOid;
bool defined;
- /*** Initialize our left and right argument types ***/
+ /* Initialize our left and right argument types */
if (typenode1 != NULL)
lefttype = TypeNameToInternalName(typenode1);
if (typenode2 != NULL)
righttype = TypeNameToInternalName(typenode2);
- /*** Attempt to fetch the left oid, if specified ***/
+ /* Attempt to fetch the left oid, if specified */
if (lefttype != NULL)
{
@@ -676,7 +739,7 @@ CommentOperator(char *opername, List *arguments, char *comment)
elog(ERROR, "left type '%s' does not exist", lefttype);
}
- /*** Attempt to fetch the right oid, if specified ***/
+ /* Attempt to fetch the right oid, if specified */
if (righttype != NULL)
{
@@ -685,7 +748,7 @@ CommentOperator(char *opername, List *arguments, char *comment)
elog(ERROR, "right type '%s' does not exist", righttype);
}
- /*** Determine operator type ***/
+ /* Determine operator type */
if (OidIsValid(leftoid) && (OidIsValid(rightoid)))
oprtype = 'b';
@@ -696,7 +759,7 @@ CommentOperator(char *opername, List *arguments, char *comment)
else
elog(ERROR, "operator '%s' is of an illegal type'", opername);
- /*** Attempt to fetch the operator oid ***/
+ /* Attempt to fetch the operator oid */
optuple = SearchSysCache(OPERNAME,
PointerGetDatum(opername),
@@ -708,13 +771,13 @@ CommentOperator(char *opername, List *arguments, char *comment)
oid = optuple->t_data->t_oid;
- /*** Valid user's ability to comment on this operator ***/
+ /* Valid user's ability to comment on this operator */
if (!pg_oper_ownercheck(GetUserId(), oid))
elog(ERROR, "you are not permitted to comment on operator '%s'",
opername);
- /*** Get the procedure associated with the operator ***/
+ /* Get the procedure associated with the operator */
data = (Form_pg_operator) GETSTRUCT(optuple);
oid = data->oprcode;
@@ -723,9 +786,9 @@ CommentOperator(char *opername, List *arguments, char *comment)
ReleaseSysCache(optuple);
- /*** Call CreateComments() to create/drop the comments ***/
+ /* Call CreateComments() to create/drop the comments */
- CreateComments(oid, comment);
+ CreateComments(oid, RelOid_pg_proc, 0, comment);
}
/*------------------------------------------------------------------
@@ -742,55 +805,48 @@ CommentOperator(char *opername, List *arguments, char *comment)
static 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;
+ ScanKeyData entry[2];
+ Oid oid;
- /*** First, validate the user's action ***/
+ /* First, validate the user's action */
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'",
trigger, "defined for relation", relname);
- /*** Now, fetch the trigger oid from pg_trigger ***/
+ /* 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);
+ ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_trigger_tgrelid,
+ F_OIDEQ,
+ ObjectIdGetDatum(RelationGetRelid(relation)));
+ ScanKeyEntryInitialize(&entry[1], 0x0, Anum_pg_trigger_tgname,
+ F_NAMEEQ,
+ NameGetDatum(trigger));
+ scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 2, 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 no trigger exists for the relation specified, notify user */
- if (oid == InvalidOid)
- {
+ if (!HeapTupleIsValid(triggertuple))
elog(ERROR, "trigger '%s' defined for relation '%s' does not exist",
trigger, relname);
- }
- /*** Create the comments with the pg_trigger oid ***/
+ oid = triggertuple->t_data->t_oid;
- CreateComments(oid, comment);
+ heap_endscan(scan);
- /*** Complete the scan and close any opened relations ***/
+ /* Create the comments with the pg_trigger oid */
+
+ CreateComments(oid, RelationGetRelid(pg_trigger), 0, comment);
+
+ /* Done, but hold lock on relation */
- heap_endscan(scan);
heap_close(pg_trigger, AccessShareLock);
heap_close(relation, NoLock);
}