Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions

comment.h File Reference

#include "nodes/parsenodes.h"
Include dependency graph for comment.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

Oid CommentObject (CommentStmt *stmt)
void DeleteComments (Oid oid, Oid classoid, int32 subid)
void CreateComments (Oid oid, Oid classoid, int32 subid, char *comment)
void DeleteSharedComments (Oid oid, Oid classoid)
void CreateSharedComments (Oid oid, Oid classoid, char *comment)
char * GetComment (Oid oid, Oid classoid, int32 subid)

Function Documentation

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;
}

void CreateComments ( Oid  oid,
Oid  classoid,
int32  subid,
char *  comment 
)

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);
}

void CreateSharedComments ( Oid  oid,
Oid  classoid,
char *  comment 
)

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);
}

void DeleteComments ( Oid  oid,
Oid  classoid,
int32  subid 
)
void DeleteSharedComments ( Oid  oid,
Oid  classoid 
)
char* GetComment ( Oid  oid,
Oid  classoid,
int32  subid 
)

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;
}