#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/indexing.h"
#include "catalog/objectaddress.h"
#include "catalog/pg_description.h"
#include "catalog/pg_shdescription.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
#include "utils/tqual.h"
Go to the source code of this file.
Functions | |
Oid | CommentObject (CommentStmt *stmt) |
void | CreateComments (Oid oid, Oid classoid, int32 subid, char *comment) |
void | CreateSharedComments (Oid oid, Oid classoid, char *comment) |
void | DeleteComments (Oid oid, Oid classoid, int32 subid) |
void | DeleteSharedComments (Oid oid, Oid classoid) |
char * | GetComment (Oid oid, Oid classoid, int32 subid) |
Oid CommentObject | ( | CommentStmt * | stmt | ) |
Definition at line 40 of file comment.c.
References check_object_ownership(), ObjectAddress::classId, CommentStmt::comment, CreateComments(), CreateSharedComments(), ereport, errcode(), errmsg(), ERROR, get_database_oid(), get_object_address(), GetUserId(), linitial, list_length(), NoLock, NULL, CommentStmt::objargs, OBJECT_COLUMN, OBJECT_DATABASE, OBJECT_ROLE, OBJECT_TABLESPACE, ObjectAddress::objectId, ObjectAddress::objectSubId, CommentStmt::objname, CommentStmt::objtype, OidIsValid, RelationData::rd_rel, relation_close(), RelationGetRelationName, RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_VIEW, ShareUpdateExclusiveLock, strVal, and WARNING.
Referenced by standard_ProcessUtility().
{ ObjectAddress address; Relation relation; /* * 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 * case. (If the length of stmt->objname is not 1, get_object_address * will throw an error below; that's OK.) */ if (stmt->objtype == OBJECT_DATABASE && list_length(stmt->objname) == 1) { char *database = strVal(linitial(stmt->objname)); if (!OidIsValid(get_database_oid(database, true))) { ereport(WARNING, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%s\" does not exist", database))); return InvalidOid; } } /* * 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. */ address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs, &relation, ShareUpdateExclusiveLock, false); /* Require ownership of the target object. */ check_object_ownership(GetUserId(), stmt->objtype, address, stmt->objname, stmt->objargs, relation); /* Perform other integrity checks as needed. */ switch (stmt->objtype) { case OBJECT_COLUMN: /* * 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. */ if (relation->rd_rel->relkind != RELKIND_RELATION && relation->rd_rel->relkind != RELKIND_VIEW && relation->rd_rel->relkind != RELKIND_MATVIEW && relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE && relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table, view, composite type, or foreign table", RelationGetRelationName(relation)))); break; default: break; } /* * 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 || stmt->objtype == OBJECT_ROLE) 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); return address.objectId; }
Definition at line 142 of file comment.c.
References Anum_pg_description_classoid, Anum_pg_description_description, Anum_pg_description_objoid, Anum_pg_description_objsubid, BTEqualStrategyNumber, CatalogUpdateIndexes(), CStringGetTextDatum, DescriptionObjIndexId, DescriptionRelationId, heap_close, heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), heap_open(), i, Int32GetDatum, NoLock, NULL, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), simple_heap_insert(), simple_heap_update(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and values.
Referenced by CommentObject(), CreateExtension(), and DefineIndex().
{ Relation description; ScanKeyData skey[3]; SysScanDesc sd; HeapTuple oldtuple; HeapTuple newtuple = NULL; Datum values[Natts_pg_description]; bool nulls[Natts_pg_description]; bool replaces[Natts_pg_description]; 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_description; i++) { nulls[i] = false; replaces[i] = true; } 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); } /* 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, RowExclusiveLock); sd = systable_beginscan(description, DescriptionObjIndexId, true, SnapshotNow, 3, skey); while ((oldtuple = systable_getnext(sd)) != NULL) { /* Found the old tuple, so delete or update it */ if (comment == NULL) simple_heap_delete(description, &oldtuple->t_self); else { newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(description), values, nulls, replaces); simple_heap_update(description, &oldtuple->t_self, newtuple); } break; /* Assume there can be only one match */ } systable_endscan(sd); /* If we didn't find an old tuple, insert a new one */ if (newtuple == NULL && comment != NULL) { newtuple = heap_form_tuple(RelationGetDescr(description), values, nulls); simple_heap_insert(description, newtuple); } /* Update indexes, if necessary */ if (newtuple != NULL) { CatalogUpdateIndexes(description, newtuple); heap_freetuple(newtuple); } /* Done */ heap_close(description, NoLock); }
Definition at line 241 of file comment.c.
References Anum_pg_shdescription_classoid, Anum_pg_shdescription_description, Anum_pg_shdescription_objoid, BTEqualStrategyNumber, CatalogUpdateIndexes(), CStringGetTextDatum, heap_close, heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), heap_open(), i, NoLock, NULL, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), SharedDescriptionObjIndexId, SharedDescriptionRelationId, simple_heap_delete(), simple_heap_insert(), simple_heap_update(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and values.
Referenced by CommentObject().
{ Relation shdescription; ScanKeyData skey[2]; SysScanDesc sd; HeapTuple oldtuple; HeapTuple newtuple = NULL; Datum values[Natts_pg_shdescription]; bool nulls[Natts_pg_shdescription]; bool replaces[Natts_pg_shdescription]; 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++) { nulls[i] = false; replaces[i] = true; } values[Anum_pg_shdescription_objoid - 1] = ObjectIdGetDatum(oid); values[Anum_pg_shdescription_classoid - 1] = ObjectIdGetDatum(classoid); values[Anum_pg_shdescription_description - 1] = CStringGetTextDatum(comment); } /* Use the index to search for a matching old tuple */ ScanKeyInit(&skey[0], Anum_pg_shdescription_objoid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(oid)); ScanKeyInit(&skey[1], Anum_pg_shdescription_classoid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classoid)); shdescription = heap_open(SharedDescriptionRelationId, RowExclusiveLock); sd = systable_beginscan(shdescription, SharedDescriptionObjIndexId, true, SnapshotNow, 2, skey); 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 { newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(shdescription), values, nulls, replaces); simple_heap_update(shdescription, &oldtuple->t_self, newtuple); } break; /* Assume there can be only one match */ } systable_endscan(sd); /* If we didn't find an old tuple, insert a new one */ if (newtuple == NULL && comment != NULL) { newtuple = heap_form_tuple(RelationGetDescr(shdescription), values, nulls); simple_heap_insert(shdescription, newtuple); } /* Update indexes, if necessary */ if (newtuple != NULL) { CatalogUpdateIndexes(shdescription, newtuple); heap_freetuple(newtuple); } /* Done */ heap_close(shdescription, NoLock); }
Definition at line 333 of file comment.c.
References Anum_pg_description_classoid, Anum_pg_description_objoid, Anum_pg_description_objsubid, BTEqualStrategyNumber, DescriptionObjIndexId, DescriptionRelationId, heap_close, heap_open(), Int32GetDatum, NULL, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by deleteOneObject().
{ Relation description; ScanKeyData skey[3]; int nkeys; SysScanDesc sd; HeapTuple oldtuple; /* Use the index to search for all matching old tuples */ ScanKeyInit(&skey[0], Anum_pg_description_objoid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(oid)); ScanKeyInit(&skey[1], Anum_pg_description_classoid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classoid)); if (subid != 0) { ScanKeyInit(&skey[2], Anum_pg_description_objsubid, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(subid)); nkeys = 3; } else nkeys = 2; description = heap_open(DescriptionRelationId, RowExclusiveLock); sd = systable_beginscan(description, DescriptionObjIndexId, true, SnapshotNow, nkeys, skey); while ((oldtuple = systable_getnext(sd)) != NULL) simple_heap_delete(description, &oldtuple->t_self); /* Done */ systable_endscan(sd); heap_close(description, RowExclusiveLock); }
Definition at line 381 of file comment.c.
References Anum_pg_shdescription_classoid, Anum_pg_shdescription_objoid, BTEqualStrategyNumber, heap_close, heap_open(), NULL, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), SharedDescriptionObjIndexId, SharedDescriptionRelationId, simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by dropdb(), DropRole(), and DropTableSpace().
{ Relation shdescription; ScanKeyData skey[2]; SysScanDesc sd; HeapTuple oldtuple; /* Use the index to search for all matching old tuples */ ScanKeyInit(&skey[0], Anum_pg_shdescription_objoid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(oid)); ScanKeyInit(&skey[1], Anum_pg_shdescription_classoid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classoid)); shdescription = heap_open(SharedDescriptionRelationId, RowExclusiveLock); sd = systable_beginscan(shdescription, SharedDescriptionObjIndexId, true, SnapshotNow, 2, skey); while ((oldtuple = systable_getnext(sd)) != NULL) simple_heap_delete(shdescription, &oldtuple->t_self); /* Done */ systable_endscan(sd); heap_close(shdescription, RowExclusiveLock); }
Definition at line 417 of file comment.c.
References AccessShareLock, Anum_pg_description_classoid, Anum_pg_description_description, Anum_pg_description_objoid, Anum_pg_description_objsubid, BTEqualStrategyNumber, DescriptionObjIndexId, DescriptionRelationId, heap_close, heap_getattr, heap_open(), Int32GetDatum, NULL, ObjectIdGetDatum, RelationGetDescr, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), TextDatumGetCString, and value.
Referenced by transformTableLikeClause().
{ 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); comment = NULL; while ((tuple = systable_getnext(sd)) != NULL) { Datum value; bool isnull; /* 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; }