1999-10-26 03:12:39 +00:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* comment.c
|
2000-01-10 17:14:46 +00:00
|
|
|
*
|
1999-10-26 03:12:39 +00:00
|
|
|
* PostgreSQL object comments utility code.
|
|
|
|
*
|
2013-01-01 17:15:01 -05:00
|
|
|
* Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
1999-10-26 03:12:39 +00:00
|
|
|
*
|
2001-01-23 04:32:23 +00:00
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/commands/comment.c
|
2001-01-23 04:32:23 +00:00
|
|
|
*
|
1999-10-26 03:12:39 +00:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
#include "access/genam.h"
|
1999-10-26 03:12:39 +00:00
|
|
|
#include "access/heapam.h"
|
2012-08-30 16:15:44 -04:00
|
|
|
#include "access/htup_details.h"
|
1999-10-26 03:12:39 +00:00
|
|
|
#include "catalog/indexing.h"
|
2010-08-27 11:47:41 +00:00
|
|
|
#include "catalog/objectaddress.h"
|
1999-10-26 03:12:39 +00:00
|
|
|
#include "catalog/pg_description.h"
|
2006-02-12 03:22:21 +00:00
|
|
|
#include "catalog/pg_shdescription.h"
|
1999-10-26 03:12:39 +00:00
|
|
|
#include "commands/comment.h"
|
2002-08-09 16:45:16 +00:00
|
|
|
#include "commands/dbcommands.h"
|
1999-10-26 03:12:39 +00:00
|
|
|
#include "miscadmin.h"
|
2001-06-25 21:11:45 +00:00
|
|
|
#include "utils/builtins.h"
|
2000-05-28 17:56:29 +00:00
|
|
|
#include "utils/fmgroids.h"
|
2011-03-26 00:10:07 -03:00
|
|
|
#include "utils/rel.h"
|
2008-03-26 21:10:39 +00:00
|
|
|
#include "utils/tqual.h"
|
1999-10-26 03:12:39 +00:00
|
|
|
|
2002-04-09 20:35:55 +00:00
|
|
|
|
|
|
|
/*
|
1999-10-26 03:12:39 +00:00
|
|
|
* CommentObject --
|
|
|
|
*
|
2000-01-10 17:14:46 +00:00
|
|
|
* This routine is used to add the associated comment into
|
2002-04-09 20:35:55 +00:00
|
|
|
* pg_description for the object specified by the given SQL command.
|
|
|
|
*/
|
2012-12-29 07:55:37 -05:00
|
|
|
Oid
|
2002-04-09 20:35:55 +00:00
|
|
|
CommentObject(CommentStmt *stmt)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
2011-04-10 11:42:00 -04:00
|
|
|
ObjectAddress address;
|
|
|
|
Relation relation;
|
2010-08-27 11:47:41 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When loading a dump, we may see a COMMENT ON DATABASE for the old name
|
|
|
|
* of the database. Erroring out would prevent pg_restore from completing
|
|
|
|
* (which is really pg_restore's fault, but for now we will work around
|
|
|
|
* the problem here). Consensus is that the best fix is to treat wrong
|
|
|
|
* database name as a WARNING not an ERROR; hence, the following special
|
2011-04-10 11:42:00 -04:00
|
|
|
* case. (If the length of stmt->objname is not 1, get_object_address
|
|
|
|
* will throw an error below; that's OK.)
|
2010-08-27 11:47:41 +00:00
|
|
|
*/
|
|
|
|
if (stmt->objtype == OBJECT_DATABASE && list_length(stmt->objname) == 1)
|
|
|
|
{
|
2011-04-10 11:42:00 -04:00
|
|
|
char *database = strVal(linitial(stmt->objname));
|
|
|
|
|
2010-08-27 11:47:41 +00:00
|
|
|
if (!OidIsValid(get_database_oid(database, true)))
|
|
|
|
{
|
|
|
|
ereport(WARNING,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_DATABASE),
|
|
|
|
errmsg("database \"%s\" does not exist", database)));
|
2012-12-29 07:55:37 -05:00
|
|
|
return InvalidOid;
|
2010-08-27 11:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-04-10 11:42:00 -04:00
|
|
|
* Translate the parser representation that identifies this object into an
|
|
|
|
* ObjectAddress. get_object_address() will throw an error if the object
|
|
|
|
* does not exist, and will also acquire a lock on the target to guard
|
|
|
|
* against concurrent DROP operations.
|
2010-08-27 11:47:41 +00:00
|
|
|
*/
|
|
|
|
address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
|
2011-06-27 21:17:25 -04:00
|
|
|
&relation, ShareUpdateExclusiveLock, false);
|
2010-08-27 11:47:41 +00:00
|
|
|
|
2011-03-04 16:08:24 -05:00
|
|
|
/* Require ownership of the target object. */
|
|
|
|
check_object_ownership(GetUserId(), stmt->objtype, address,
|
|
|
|
stmt->objname, stmt->objargs, relation);
|
|
|
|
|
|
|
|
/* Perform other integrity checks as needed. */
|
2002-04-09 20:35:55 +00:00
|
|
|
switch (stmt->objtype)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
2003-06-27 14:45:32 +00:00
|
|
|
case OBJECT_COLUMN:
|
2011-04-10 11:42:00 -04:00
|
|
|
|
2011-03-04 16:08:24 -05:00
|
|
|
/*
|
2013-03-03 18:23:31 -06:00
|
|
|
* Allow comments only on columns of tables, views, materialized
|
|
|
|
* views, composite types, and foreign tables (which are the only
|
|
|
|
* relkinds for which pg_dump will dump per-column comments). In
|
|
|
|
* particular we wish to disallow comments on index columns,
|
|
|
|
* because the naming of an index's columns may change across PG
|
|
|
|
* versions, so dumping per-column comments could create reload
|
|
|
|
* failures.
|
2011-03-04 16:08:24 -05:00
|
|
|
*/
|
|
|
|
if (relation->rd_rel->relkind != RELKIND_RELATION &&
|
|
|
|
relation->rd_rel->relkind != RELKIND_VIEW &&
|
2013-03-03 18:23:31 -06:00
|
|
|
relation->rd_rel->relkind != RELKIND_MATVIEW &&
|
2011-03-04 16:08:24 -05:00
|
|
|
relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
|
|
|
|
relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
|
2010-08-27 11:47:41 +00:00
|
|
|
ereport(ERROR,
|
2011-03-04 16:08:24 -05:00
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
errmsg("\"%s\" is not a table, view, composite type, or foreign table",
|
|
|
|
RelationGetRelationName(relation))));
|
2007-08-21 01:11:32 +00:00
|
|
|
break;
|
2000-04-12 17:17:23 +00:00
|
|
|
default:
|
2011-03-04 16:08:24 -05:00
|
|
|
break;
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
2010-08-27 11:47:41 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Databases, tablespaces, and roles are cluster-wide objects, so any
|
|
|
|
* comments on those objects are recorded in the shared pg_shdescription
|
|
|
|
* catalog. Comments on all other objects are recorded in pg_description.
|
|
|
|
*/
|
|
|
|
if (stmt->objtype == OBJECT_DATABASE || stmt->objtype == OBJECT_TABLESPACE
|
2010-11-23 22:27:50 +02:00
|
|
|
|| stmt->objtype == OBJECT_ROLE)
|
2010-08-27 11:47:41 +00:00
|
|
|
CreateSharedComments(address.objectId, address.classId, stmt->comment);
|
|
|
|
else
|
|
|
|
CreateComments(address.objectId, address.classId, address.objectSubId,
|
|
|
|
stmt->comment);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If get_object_address() opened the relation for us, we close it to keep
|
|
|
|
* the reference count correct - but we retain any locks acquired by
|
|
|
|
* get_object_address() until commit time, to guard against concurrent
|
|
|
|
* activity.
|
|
|
|
*/
|
|
|
|
if (relation != NULL)
|
|
|
|
relation_close(relation, NoLock);
|
2012-12-29 07:55:37 -05:00
|
|
|
|
|
|
|
return address.objectId;
|
1999-10-26 03:12:39 +00:00
|
|
|
}
|
|
|
|
|
2002-04-09 20:35:55 +00:00
|
|
|
/*
|
1999-10-26 03:12:39 +00:00
|
|
|
* CreateComments --
|
2000-01-10 17:14:46 +00:00
|
|
|
*
|
2001-08-10 18:57:42 +00:00
|
|
|
* Create a comment for the specified object descriptor. Inserts a new
|
|
|
|
* pg_description tuple, or replaces an existing one with the same key.
|
1999-10-26 03:12:39 +00:00
|
|
|
*
|
2001-08-10 18:57:42 +00:00
|
|
|
* If the comment given is null or an empty string, instead delete any
|
|
|
|
* existing comment for the specified key.
|
1999-10-26 03:12:39 +00:00
|
|
|
*/
|
2001-08-10 18:57:42 +00:00
|
|
|
void
|
|
|
|
CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
|
|
|
Relation description;
|
2001-08-10 18:57:42 +00:00
|
|
|
ScanKeyData skey[3];
|
2002-05-20 23:51:44 +00:00
|
|
|
SysScanDesc sd;
|
|
|
|
HeapTuple oldtuple;
|
2001-08-10 18:57:42 +00:00
|
|
|
HeapTuple newtuple = NULL;
|
2000-04-12 17:17:23 +00:00
|
|
|
Datum values[Natts_pg_description];
|
2008-11-02 01:45:28 +00:00
|
|
|
bool nulls[Natts_pg_description];
|
|
|
|
bool replaces[Natts_pg_description];
|
2000-04-12 17:17:23 +00:00
|
|
|
int i;
|
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
/* Reduce empty-string to NULL case */
|
|
|
|
if (comment != NULL && strlen(comment) == 0)
|
|
|
|
comment = NULL;
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
/* Prepare to form or update a tuple, if necessary */
|
|
|
|
if (comment != NULL)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
|
|
|
for (i = 0; i < Natts_pg_description; i++)
|
|
|
|
{
|
2008-11-02 01:45:28 +00:00
|
|
|
nulls[i] = false;
|
|
|
|
replaces[i] = true;
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
2011-06-16 17:03:58 -04:00
|
|
|
values[Anum_pg_description_objoid - 1] = ObjectIdGetDatum(oid);
|
|
|
|
values[Anum_pg_description_classoid - 1] = ObjectIdGetDatum(classoid);
|
|
|
|
values[Anum_pg_description_objsubid - 1] = Int32GetDatum(subid);
|
|
|
|
values[Anum_pg_description_description - 1] = CStringGetTextDatum(comment);
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
/* Use the index to search for a matching old tuple */
|
|
|
|
|
2003-11-12 21:15:59 +00:00
|
|
|
ScanKeyInit(&skey[0],
|
|
|
|
Anum_pg_description_objoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(oid));
|
|
|
|
ScanKeyInit(&skey[1],
|
|
|
|
Anum_pg_description_classoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(classoid));
|
|
|
|
ScanKeyInit(&skey[2],
|
|
|
|
Anum_pg_description_objsubid,
|
|
|
|
BTEqualStrategyNumber, F_INT4EQ,
|
|
|
|
Int32GetDatum(subid));
|
2001-08-10 18:57:42 +00:00
|
|
|
|
2005-04-14 20:03:27 +00:00
|
|
|
description = heap_open(DescriptionRelationId, RowExclusiveLock);
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2005-04-14 20:03:27 +00:00
|
|
|
sd = systable_beginscan(description, DescriptionObjIndexId, true,
|
2002-05-20 23:51:44 +00:00
|
|
|
SnapshotNow, 3, skey);
|
2001-08-10 18:57:42 +00:00
|
|
|
|
2002-05-20 23:51:44 +00:00
|
|
|
while ((oldtuple = systable_getnext(sd)) != NULL)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
2001-08-10 18:57:42 +00:00
|
|
|
/* Found the old tuple, so delete or update it */
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
if (comment == NULL)
|
2002-05-20 23:51:44 +00:00
|
|
|
simple_heap_delete(description, &oldtuple->t_self);
|
2000-04-12 17:17:23 +00:00
|
|
|
else
|
|
|
|
{
|
2008-11-02 01:45:28 +00:00
|
|
|
newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(description), values,
|
2009-06-11 14:49:15 +00:00
|
|
|
nulls, replaces);
|
2002-05-20 23:51:44 +00:00
|
|
|
simple_heap_update(description, &oldtuple->t_self, newtuple);
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
break; /* Assume there can be only one match */
|
2000-01-20 15:13:19 +00:00
|
|
|
}
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2002-05-20 23:51:44 +00:00
|
|
|
systable_endscan(sd);
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
/* If we didn't find an old tuple, insert a new one */
|
2000-01-20 15:13:19 +00:00
|
|
|
|
2002-05-20 23:51:44 +00:00
|
|
|
if (newtuple == NULL && comment != NULL)
|
2001-08-10 18:57:42 +00:00
|
|
|
{
|
2008-11-02 01:45:28 +00:00
|
|
|
newtuple = heap_form_tuple(RelationGetDescr(description),
|
2009-06-11 14:49:15 +00:00
|
|
|
values, nulls);
|
2002-05-21 22:05:55 +00:00
|
|
|
simple_heap_insert(description, newtuple);
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
1999-10-26 03:12:39 +00:00
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
/* Update indexes, if necessary */
|
|
|
|
if (newtuple != NULL)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
2002-08-05 03:29:17 +00:00
|
|
|
CatalogUpdateIndexes(description, newtuple);
|
2001-08-10 18:57:42 +00:00
|
|
|
heap_freetuple(newtuple);
|
2000-04-12 17:17:23 +00:00
|
|
|
}
|
1999-10-26 03:12:39 +00:00
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
/* Done */
|
1999-10-26 03:12:39 +00:00
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
heap_close(description, NoLock);
|
1999-10-26 03:12:39 +00:00
|
|
|
}
|
|
|
|
|
2006-02-12 03:22:21 +00:00
|
|
|
/*
|
|
|
|
* CreateSharedComments --
|
|
|
|
*
|
|
|
|
* Create a comment for the specified shared object descriptor. Inserts a
|
|
|
|
* new pg_shdescription 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.
|
|
|
|
*/
|
2006-10-04 00:30:14 +00:00
|
|
|
void
|
|
|
|
CreateSharedComments(Oid oid, Oid classoid, char *comment)
|
2006-02-12 03:22:21 +00:00
|
|
|
{
|
|
|
|
Relation shdescription;
|
2006-10-04 00:30:14 +00:00
|
|
|
ScanKeyData skey[2];
|
|
|
|
SysScanDesc sd;
|
2006-02-12 03:22:21 +00:00
|
|
|
HeapTuple oldtuple;
|
|
|
|
HeapTuple newtuple = NULL;
|
|
|
|
Datum values[Natts_pg_shdescription];
|
2008-11-02 01:45:28 +00:00
|
|
|
bool nulls[Natts_pg_shdescription];
|
|
|
|
bool replaces[Natts_pg_shdescription];
|
2006-02-12 03:22:21 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Reduce empty-string to NULL case */
|
|
|
|
if (comment != NULL && strlen(comment) == 0)
|
|
|
|
comment = NULL;
|
|
|
|
|
|
|
|
/* Prepare to form or update a tuple, if necessary */
|
|
|
|
if (comment != NULL)
|
|
|
|
{
|
|
|
|
for (i = 0; i < Natts_pg_shdescription; i++)
|
|
|
|
{
|
2008-11-02 01:45:28 +00:00
|
|
|
nulls[i] = false;
|
|
|
|
replaces[i] = true;
|
2006-02-12 03:22:21 +00:00
|
|
|
}
|
2011-06-16 17:03:58 -04:00
|
|
|
values[Anum_pg_shdescription_objoid - 1] = ObjectIdGetDatum(oid);
|
|
|
|
values[Anum_pg_shdescription_classoid - 1] = ObjectIdGetDatum(classoid);
|
|
|
|
values[Anum_pg_shdescription_description - 1] = CStringGetTextDatum(comment);
|
2006-02-12 03:22:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Use the index to search for a matching old tuple */
|
|
|
|
|
|
|
|
ScanKeyInit(&skey[0],
|
2006-10-04 00:30:14 +00:00
|
|
|
Anum_pg_shdescription_objoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(oid));
|
2006-02-12 03:22:21 +00:00
|
|
|
ScanKeyInit(&skey[1],
|
2006-10-04 00:30:14 +00:00
|
|
|
Anum_pg_shdescription_classoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(classoid));
|
2006-02-12 03:22:21 +00:00
|
|
|
|
|
|
|
shdescription = heap_open(SharedDescriptionRelationId, RowExclusiveLock);
|
|
|
|
|
|
|
|
sd = systable_beginscan(shdescription, SharedDescriptionObjIndexId, true,
|
2006-10-04 00:30:14 +00:00
|
|
|
SnapshotNow, 2, skey);
|
2006-02-12 03:22:21 +00:00
|
|
|
|
|
|
|
while ((oldtuple = systable_getnext(sd)) != NULL)
|
|
|
|
{
|
|
|
|
/* Found the old tuple, so delete or update it */
|
|
|
|
|
|
|
|
if (comment == NULL)
|
|
|
|
simple_heap_delete(shdescription, &oldtuple->t_self);
|
|
|
|
else
|
|
|
|
{
|
2008-11-02 01:45:28 +00:00
|
|
|
newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(shdescription),
|
2009-06-11 14:49:15 +00:00
|
|
|
values, nulls, replaces);
|
2006-02-12 03:22:21 +00:00
|
|
|
simple_heap_update(shdescription, &oldtuple->t_self, newtuple);
|
|
|
|
}
|
|
|
|
|
2006-10-04 00:30:14 +00:00
|
|
|
break; /* Assume there can be only one match */
|
2006-02-12 03:22:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
systable_endscan(sd);
|
|
|
|
|
|
|
|
/* If we didn't find an old tuple, insert a new one */
|
|
|
|
|
|
|
|
if (newtuple == NULL && comment != NULL)
|
|
|
|
{
|
2008-11-02 01:45:28 +00:00
|
|
|
newtuple = heap_form_tuple(RelationGetDescr(shdescription),
|
2009-06-11 14:49:15 +00:00
|
|
|
values, nulls);
|
2006-02-12 03:22:21 +00:00
|
|
|
simple_heap_insert(shdescription, newtuple);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update indexes, if necessary */
|
|
|
|
if (newtuple != NULL)
|
|
|
|
{
|
|
|
|
CatalogUpdateIndexes(shdescription, newtuple);
|
|
|
|
heap_freetuple(newtuple);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Done */
|
|
|
|
|
|
|
|
heap_close(shdescription, NoLock);
|
|
|
|
}
|
|
|
|
|
2002-04-09 20:35:55 +00:00
|
|
|
/*
|
2002-07-12 18:43:19 +00:00
|
|
|
* DeleteComments -- remove comments for an object
|
1999-10-26 03:12:39 +00:00
|
|
|
*
|
2002-07-12 18:43:19 +00:00
|
|
|
* If subid is nonzero then only comments matching it will be removed.
|
|
|
|
* If subid is zero, all comments matching the oid/classoid will be removed
|
|
|
|
* (this corresponds to deleting a whole object).
|
1999-10-26 03:12:39 +00:00
|
|
|
*/
|
2000-04-12 17:17:23 +00:00
|
|
|
void
|
2002-07-12 18:43:19 +00:00
|
|
|
DeleteComments(Oid oid, Oid classoid, int32 subid)
|
2000-04-12 17:17:23 +00:00
|
|
|
{
|
|
|
|
Relation description;
|
2002-07-12 18:43:19 +00:00
|
|
|
ScanKeyData skey[3];
|
|
|
|
int nkeys;
|
2002-09-04 20:31:48 +00:00
|
|
|
SysScanDesc sd;
|
2002-05-20 23:51:44 +00:00
|
|
|
HeapTuple oldtuple;
|
1999-10-26 03:12:39 +00:00
|
|
|
|
2001-08-10 18:57:42 +00:00
|
|
|
/* Use the index to search for all matching old tuples */
|
2000-01-10 17:14:46 +00:00
|
|
|
|
2003-11-12 21:15:59 +00:00
|
|
|
ScanKeyInit(&skey[0],
|
|
|
|
Anum_pg_description_objoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(oid));
|
|
|
|
ScanKeyInit(&skey[1],
|
|
|
|
Anum_pg_description_classoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(classoid));
|
2001-08-10 18:57:42 +00:00
|
|
|
|
2002-07-12 18:43:19 +00:00
|
|
|
if (subid != 0)
|
|
|
|
{
|
2003-11-12 21:15:59 +00:00
|
|
|
ScanKeyInit(&skey[2],
|
|
|
|
Anum_pg_description_objsubid,
|
|
|
|
BTEqualStrategyNumber, F_INT4EQ,
|
|
|
|
Int32GetDatum(subid));
|
2002-07-12 18:43:19 +00:00
|
|
|
nkeys = 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
nkeys = 2;
|
|
|
|
|
2005-04-14 20:03:27 +00:00
|
|
|
description = heap_open(DescriptionRelationId, RowExclusiveLock);
|
1999-10-26 03:12:39 +00:00
|
|
|
|
2005-04-14 20:03:27 +00:00
|
|
|
sd = systable_beginscan(description, DescriptionObjIndexId, true,
|
2002-07-12 18:43:19 +00:00
|
|
|
SnapshotNow, nkeys, skey);
|
2001-08-10 18:57:42 +00:00
|
|
|
|
2002-05-20 23:51:44 +00:00
|
|
|
while ((oldtuple = systable_getnext(sd)) != NULL)
|
|
|
|
simple_heap_delete(description, &oldtuple->t_self);
|
2001-08-10 18:57:42 +00:00
|
|
|
|
|
|
|
/* Done */
|
2000-01-10 17:14:46 +00:00
|
|
|
|
2002-05-20 23:51:44 +00:00
|
|
|
systable_endscan(sd);
|
2002-07-12 18:43:19 +00:00
|
|
|
heap_close(description, RowExclusiveLock);
|
1999-10-26 03:12:39 +00:00
|
|
|
}
|
2000-01-10 17:14:46 +00:00
|
|
|
|
2006-02-12 03:22:21 +00:00
|
|
|
/*
|
|
|
|
* DeleteSharedComments -- remove comments for a shared object
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
DeleteSharedComments(Oid oid, Oid classoid)
|
|
|
|
{
|
|
|
|
Relation shdescription;
|
2006-10-04 00:30:14 +00:00
|
|
|
ScanKeyData skey[2];
|
|
|
|
SysScanDesc sd;
|
2006-02-12 03:22:21 +00:00
|
|
|
HeapTuple oldtuple;
|
|
|
|
|
|
|
|
/* Use the index to search for all matching old tuples */
|
|
|
|
|
|
|
|
ScanKeyInit(&skey[0],
|
2006-10-04 00:30:14 +00:00
|
|
|
Anum_pg_shdescription_objoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(oid));
|
2006-02-12 03:22:21 +00:00
|
|
|
ScanKeyInit(&skey[1],
|
2006-10-04 00:30:14 +00:00
|
|
|
Anum_pg_shdescription_classoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(classoid));
|
2006-02-12 03:22:21 +00:00
|
|
|
|
|
|
|
shdescription = heap_open(SharedDescriptionRelationId, RowExclusiveLock);
|
|
|
|
|
|
|
|
sd = systable_beginscan(shdescription, SharedDescriptionObjIndexId, true,
|
2006-10-04 00:30:14 +00:00
|
|
|
SnapshotNow, 2, skey);
|
2006-02-12 03:22:21 +00:00
|
|
|
|
|
|
|
while ((oldtuple = systable_getnext(sd)) != NULL)
|
|
|
|
simple_heap_delete(shdescription, &oldtuple->t_self);
|
|
|
|
|
|
|
|
/* Done */
|
|
|
|
|
|
|
|
systable_endscan(sd);
|
|
|
|
heap_close(shdescription, RowExclusiveLock);
|
|
|
|
}
|
|
|
|
|
2009-10-12 19:49:24 +00:00
|
|
|
/*
|
|
|
|
* GetComment -- get the comment for an object, or null if not found.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
GetComment(Oid oid, Oid classoid, int32 subid)
|
|
|
|
{
|
|
|
|
Relation description;
|
|
|
|
ScanKeyData skey[3];
|
|
|
|
SysScanDesc sd;
|
|
|
|
TupleDesc tupdesc;
|
|
|
|
HeapTuple tuple;
|
|
|
|
char *comment;
|
|
|
|
|
|
|
|
/* Use the index to search for a matching old tuple */
|
|
|
|
|
|
|
|
ScanKeyInit(&skey[0],
|
|
|
|
Anum_pg_description_objoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(oid));
|
|
|
|
ScanKeyInit(&skey[1],
|
|
|
|
Anum_pg_description_classoid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(classoid));
|
|
|
|
ScanKeyInit(&skey[2],
|
|
|
|
Anum_pg_description_objsubid,
|
|
|
|
BTEqualStrategyNumber, F_INT4EQ,
|
|
|
|
Int32GetDatum(subid));
|
|
|
|
|
|
|
|
description = heap_open(DescriptionRelationId, AccessShareLock);
|
|
|
|
tupdesc = RelationGetDescr(description);
|
|
|
|
|
|
|
|
sd = systable_beginscan(description, DescriptionObjIndexId, true,
|
|
|
|
SnapshotNow, 3, skey);
|
|
|
|
|
2010-02-26 02:01:40 +00:00
|
|
|
comment = NULL;
|
2009-10-12 19:49:24 +00:00
|
|
|
while ((tuple = systable_getnext(sd)) != NULL)
|
|
|
|
{
|
2010-02-26 02:01:40 +00:00
|
|
|
Datum value;
|
|
|
|
bool isnull;
|
2009-10-12 19:49:24 +00:00
|
|
|
|
|
|
|
/* Found the tuple, get description field */
|
|
|
|
value = heap_getattr(tuple, Anum_pg_description_description, tupdesc, &isnull);
|
|
|
|
if (!isnull)
|
|
|
|
comment = TextDatumGetCString(value);
|
|
|
|
break; /* Assume there can be only one match */
|
|
|
|
}
|
|
|
|
|
|
|
|
systable_endscan(sd);
|
|
|
|
|
|
|
|
/* Done */
|
|
|
|
heap_close(description, AccessShareLock);
|
|
|
|
|
|
|
|
return comment;
|
|
|
|
}
|