Header And Logo

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

Functions

pg_constraint.c File Reference

#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for pg_constraint.c:

Go to the source code of this file.

Functions

Oid CreateConstraintEntry (const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid relId, const int16 *constraintKey, int constraintNKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, const char *conSrc, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
bool ConstraintNameIsUsed (ConstraintCategory conCat, Oid objId, Oid objNamespace, const char *conname)
char * ChooseConstraintName (const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
void RemoveConstraintById (Oid conId)
void RenameConstraintById (Oid conId, const char *newname)
void AlterConstraintNamespaces (Oid ownerId, Oid oldNspId, Oid newNspId, bool isType, ObjectAddresses *objsMoved)
Oid get_relation_constraint_oid (Oid relid, const char *conname, bool missing_ok)
Oid get_domain_constraint_oid (Oid typid, const char *conname, bool missing_ok)
bool check_functional_grouping (Oid relid, Index varno, Index varlevelsup, List *grouping_columns, List **constraintDeps)

Function Documentation

void AlterConstraintNamespaces ( Oid  ownerId,
Oid  oldNspId,
Oid  newNspId,
bool  isType,
ObjectAddresses *  objsMoved 
)

Definition at line 684 of file pg_constraint.c.

References add_exact_object_address(), Anum_pg_constraint_conrelid, Anum_pg_constraint_contypid, BTEqualStrategyNumber, CatalogUpdateIndexes(), ObjectAddress::classId, ConstraintRelationId, ConstraintRelidIndexId, ConstraintTypidIndexId, GETSTRUCT, heap_close, heap_copytuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvokeObjectPostAlterHook, object_address_present(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), simple_heap_update(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by AlterTableNamespaceInternal(), and AlterTypeNamespaceInternal().

{
    Relation    conRel;
    ScanKeyData key[1];
    SysScanDesc scan;
    HeapTuple   tup;

    conRel = heap_open(ConstraintRelationId, RowExclusiveLock);

    if (isType)
    {
        ScanKeyInit(&key[0],
                    Anum_pg_constraint_contypid,
                    BTEqualStrategyNumber, F_OIDEQ,
                    ObjectIdGetDatum(ownerId));

        scan = systable_beginscan(conRel, ConstraintTypidIndexId, true,
                                  SnapshotNow, 1, key);
    }
    else
    {
        ScanKeyInit(&key[0],
                    Anum_pg_constraint_conrelid,
                    BTEqualStrategyNumber, F_OIDEQ,
                    ObjectIdGetDatum(ownerId));

        scan = systable_beginscan(conRel, ConstraintRelidIndexId, true,
                                  SnapshotNow, 1, key);
    }

    while (HeapTupleIsValid((tup = systable_getnext(scan))))
    {
        Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(tup);
        ObjectAddress   thisobj;

        thisobj.classId = ConstraintRelationId;
        thisobj.objectId = HeapTupleGetOid(tup);
        thisobj.objectSubId = 0;

        if (object_address_present(&thisobj, objsMoved))
            continue;

        if (conform->connamespace == oldNspId)
        {
            tup = heap_copytuple(tup);
            conform = (Form_pg_constraint) GETSTRUCT(tup);

            conform->connamespace = newNspId;

            simple_heap_update(conRel, &tup->t_self, tup);
            CatalogUpdateIndexes(conRel, tup);

            /*
             * Note: currently, the constraint will not have its own
             * dependency on the namespace, so we don't need to do
             * changeDependencyFor().
             */
        }

        InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);

        add_exact_object_address(&thisobj, objsMoved);
    }

    systable_endscan(scan);

    heap_close(conRel, RowExclusiveLock);
}

bool check_functional_grouping ( Oid  relid,
Index  varno,
Index  varlevelsup,
List *  grouping_columns,
List **  constraintDeps 
)

Definition at line 886 of file pg_constraint.c.

References AccessShareLock, Anum_pg_constraint_conkey, Anum_pg_constraint_conrelid, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, CONSTRAINT_PRIMARY, ConstraintRelationId, ConstraintRelidIndexId, DatumGetArrayTypeP, elog, ERROR, GETSTRUCT, heap_close, heap_getattr, heap_open(), HeapTupleGetOid, HeapTupleIsValid, i, INT2OID, IsA, lappend_oid(), lfirst, ObjectIdGetDatum, RelationGetDescr, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by check_ungrouped_columns_walker().

{
    bool        result = false;
    Relation    pg_constraint;
    HeapTuple   tuple;
    SysScanDesc scan;
    ScanKeyData skey[1];

    /* Scan pg_constraint for constraints of the target rel */
    pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);

    ScanKeyInit(&skey[0],
                Anum_pg_constraint_conrelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(relid));

    scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
                              SnapshotNow, 1, skey);

    while (HeapTupleIsValid(tuple = systable_getnext(scan)))
    {
        Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
        Datum       adatum;
        bool        isNull;
        ArrayType  *arr;
        int16      *attnums;
        int         numkeys;
        int         i;
        bool        found_col;

        /* Only PK constraints are of interest for now, see comment above */
        if (con->contype != CONSTRAINT_PRIMARY)
            continue;
        /* Constraint must be non-deferrable */
        if (con->condeferrable)
            continue;

        /* Extract the conkey array, ie, attnums of PK's columns */
        adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
                              RelationGetDescr(pg_constraint), &isNull);
        if (isNull)
            elog(ERROR, "null conkey for constraint %u",
                 HeapTupleGetOid(tuple));
        arr = DatumGetArrayTypeP(adatum);       /* ensure not toasted */
        numkeys = ARR_DIMS(arr)[0];
        if (ARR_NDIM(arr) != 1 ||
            numkeys < 0 ||
            ARR_HASNULL(arr) ||
            ARR_ELEMTYPE(arr) != INT2OID)
            elog(ERROR, "conkey is not a 1-D smallint array");
        attnums = (int16 *) ARR_DATA_PTR(arr);

        found_col = false;
        for (i = 0; i < numkeys; i++)
        {
            AttrNumber  attnum = attnums[i];
            ListCell   *gl;

            found_col = false;
            foreach(gl, grouping_columns)
            {
                Var        *gvar = (Var *) lfirst(gl);

                if (IsA(gvar, Var) &&
                    gvar->varno == varno &&
                    gvar->varlevelsup == varlevelsup &&
                    gvar->varattno == attnum)
                {
                    found_col = true;
                    break;
                }
            }
            if (!found_col)
                break;
        }

        if (found_col)
        {
            /* The PK is a subset of grouping_columns, so we win */
            *constraintDeps = lappend_oid(*constraintDeps,
                                          HeapTupleGetOid(tuple));
            result = true;
            break;
        }
    }

    systable_endscan(scan);

    heap_close(pg_constraint, AccessShareLock);

    return result;
}

char* ChooseConstraintName ( const char *  name1,
const char *  name2,
const char *  label,
Oid  namespaceid,
List *  others 
)

Definition at line 463 of file pg_constraint.c.

References AccessShareLock, Anum_pg_constraint_conname, Anum_pg_constraint_connamespace, BTEqualStrategyNumber, ConstraintNameNspIndexId, ConstraintRelationId, CStringGetDatum, heap_close, heap_open(), HeapTupleIsValid, lfirst, makeObjectName(), ObjectIdGetDatum, pfree(), ScanKeyInit(), SnapshotNow, snprintf(), StrNCpy, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by AddRelationNewConstraints(), ATExecAddConstraint(), and domainAddConstraint().

{
    int         pass = 0;
    char       *conname = NULL;
    char        modlabel[NAMEDATALEN];
    Relation    conDesc;
    SysScanDesc conscan;
    ScanKeyData skey[2];
    bool        found;
    ListCell   *l;

    conDesc = heap_open(ConstraintRelationId, AccessShareLock);

    /* try the unmodified label first */
    StrNCpy(modlabel, label, sizeof(modlabel));

    for (;;)
    {
        conname = makeObjectName(name1, name2, modlabel);

        found = false;

        foreach(l, others)
        {
            if (strcmp((char *) lfirst(l), conname) == 0)
            {
                found = true;
                break;
            }
        }

        if (!found)
        {
            ScanKeyInit(&skey[0],
                        Anum_pg_constraint_conname,
                        BTEqualStrategyNumber, F_NAMEEQ,
                        CStringGetDatum(conname));

            ScanKeyInit(&skey[1],
                        Anum_pg_constraint_connamespace,
                        BTEqualStrategyNumber, F_OIDEQ,
                        ObjectIdGetDatum(namespaceid));

            conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
                                         SnapshotNow, 2, skey);

            found = (HeapTupleIsValid(systable_getnext(conscan)));

            systable_endscan(conscan);
        }

        if (!found)
            break;

        /* found a conflict, so try a new name component */
        pfree(conname);
        snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
    }

    heap_close(conDesc, AccessShareLock);

    return conname;
}

bool ConstraintNameIsUsed ( ConstraintCategory  conCat,
Oid  objId,
Oid  objNamespace,
const char *  conname 
)
Oid CreateConstraintEntry ( const char *  constraintName,
Oid  constraintNamespace,
char  constraintType,
bool  isDeferrable,
bool  isDeferred,
bool  isValidated,
Oid  relId,
const int16 *  constraintKey,
int  constraintNKeys,
Oid  domainId,
Oid  indexRelId,
Oid  foreignRelId,
const int16 *  foreignKey,
const Oid *  pfEqOp,
const Oid *  ppEqOp,
const Oid *  ffEqOp,
int  foreignNKeys,
char  foreignUpdateType,
char  foreignDeleteType,
char  foreignMatchType,
const Oid *  exclOp,
Node *  conExpr,
const char *  conBin,
const char *  conSrc,
bool  conIsLocal,
int  conInhCount,
bool  conNoInherit,
bool  is_internal 
)

Definition at line 45 of file pg_constraint.c.

References Anum_pg_constraint_conbin, Anum_pg_constraint_condeferrable, Anum_pg_constraint_condeferred, Anum_pg_constraint_conexclop, Anum_pg_constraint_confdeltype, Anum_pg_constraint_conffeqop, Anum_pg_constraint_confkey, Anum_pg_constraint_confmatchtype, Anum_pg_constraint_confrelid, Anum_pg_constraint_confupdtype, Anum_pg_constraint_conindid, Anum_pg_constraint_coninhcount, Anum_pg_constraint_conislocal, Anum_pg_constraint_conkey, Anum_pg_constraint_conname, Anum_pg_constraint_connamespace, Anum_pg_constraint_connoinherit, Anum_pg_constraint_conpfeqop, Anum_pg_constraint_conppeqop, Anum_pg_constraint_conrelid, Anum_pg_constraint_consrc, Anum_pg_constraint_contype, Anum_pg_constraint_contypid, Anum_pg_constraint_convalidated, Assert, BoolGetDatum, CatalogUpdateIndexes(), CharGetDatum, ObjectAddress::classId, CONSTRAINT_FOREIGN, ConstraintRelationId, construct_array(), CStringGetTextDatum, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, heap_close, heap_form_tuple(), heap_open(), i, Int16GetDatum, INT2OID, Int32GetDatum, InvokeObjectPostCreateHookArg, NameGetDatum, namestrcpy(), NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, OIDOID, palloc(), PointerGetDatum, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RowExclusiveLock, simple_heap_insert(), and values.

Referenced by ATAddForeignKeyConstraint(), CreateTrigger(), domainAddConstraint(), index_constraint_create(), and StoreRelCheck().

{
    Relation    conDesc;
    Oid         conOid;
    HeapTuple   tup;
    bool        nulls[Natts_pg_constraint];
    Datum       values[Natts_pg_constraint];
    ArrayType  *conkeyArray;
    ArrayType  *confkeyArray;
    ArrayType  *conpfeqopArray;
    ArrayType  *conppeqopArray;
    ArrayType  *conffeqopArray;
    ArrayType  *conexclopArray;
    NameData    cname;
    int         i;
    ObjectAddress conobject;

    conDesc = heap_open(ConstraintRelationId, RowExclusiveLock);

    Assert(constraintName);
    namestrcpy(&cname, constraintName);

    /*
     * Convert C arrays into Postgres arrays.
     */
    if (constraintNKeys > 0)
    {
        Datum      *conkey;

        conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum));
        for (i = 0; i < constraintNKeys; i++)
            conkey[i] = Int16GetDatum(constraintKey[i]);
        conkeyArray = construct_array(conkey, constraintNKeys,
                                      INT2OID, 2, true, 's');
    }
    else
        conkeyArray = NULL;

    if (foreignNKeys > 0)
    {
        Datum      *fkdatums;

        fkdatums = (Datum *) palloc(foreignNKeys * sizeof(Datum));
        for (i = 0; i < foreignNKeys; i++)
            fkdatums[i] = Int16GetDatum(foreignKey[i]);
        confkeyArray = construct_array(fkdatums, foreignNKeys,
                                       INT2OID, 2, true, 's');
        for (i = 0; i < foreignNKeys; i++)
            fkdatums[i] = ObjectIdGetDatum(pfEqOp[i]);
        conpfeqopArray = construct_array(fkdatums, foreignNKeys,
                                         OIDOID, sizeof(Oid), true, 'i');
        for (i = 0; i < foreignNKeys; i++)
            fkdatums[i] = ObjectIdGetDatum(ppEqOp[i]);
        conppeqopArray = construct_array(fkdatums, foreignNKeys,
                                         OIDOID, sizeof(Oid), true, 'i');
        for (i = 0; i < foreignNKeys; i++)
            fkdatums[i] = ObjectIdGetDatum(ffEqOp[i]);
        conffeqopArray = construct_array(fkdatums, foreignNKeys,
                                         OIDOID, sizeof(Oid), true, 'i');
    }
    else
    {
        confkeyArray = NULL;
        conpfeqopArray = NULL;
        conppeqopArray = NULL;
        conffeqopArray = NULL;
    }

    if (exclOp != NULL)
    {
        Datum      *opdatums;

        opdatums = (Datum *) palloc(constraintNKeys * sizeof(Datum));
        for (i = 0; i < constraintNKeys; i++)
            opdatums[i] = ObjectIdGetDatum(exclOp[i]);
        conexclopArray = construct_array(opdatums, constraintNKeys,
                                         OIDOID, sizeof(Oid), true, 'i');
    }
    else
        conexclopArray = NULL;

    /* initialize nulls and values */
    for (i = 0; i < Natts_pg_constraint; i++)
    {
        nulls[i] = false;
        values[i] = (Datum) NULL;
    }

    values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname);
    values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace);
    values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType);
    values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable);
    values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred);
    values[Anum_pg_constraint_convalidated - 1] = BoolGetDatum(isValidated);
    values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId);
    values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId);
    values[Anum_pg_constraint_conindid - 1] = ObjectIdGetDatum(indexRelId);
    values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId);
    values[Anum_pg_constraint_confupdtype - 1] = CharGetDatum(foreignUpdateType);
    values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType);
    values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType);
    values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
    values[Anum_pg_constraint_coninhcount - 1] = Int32GetDatum(conInhCount);
    values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);

    if (conkeyArray)
        values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
    else
        nulls[Anum_pg_constraint_conkey - 1] = true;

    if (confkeyArray)
        values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray);
    else
        nulls[Anum_pg_constraint_confkey - 1] = true;

    if (conpfeqopArray)
        values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray);
    else
        nulls[Anum_pg_constraint_conpfeqop - 1] = true;

    if (conppeqopArray)
        values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray);
    else
        nulls[Anum_pg_constraint_conppeqop - 1] = true;

    if (conffeqopArray)
        values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray);
    else
        nulls[Anum_pg_constraint_conffeqop - 1] = true;

    if (conexclopArray)
        values[Anum_pg_constraint_conexclop - 1] = PointerGetDatum(conexclopArray);
    else
        nulls[Anum_pg_constraint_conexclop - 1] = true;

    /*
     * initialize the binary form of the check constraint.
     */
    if (conBin)
        values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin);
    else
        nulls[Anum_pg_constraint_conbin - 1] = true;

    /*
     * initialize the text form of the check constraint
     */
    if (conSrc)
        values[Anum_pg_constraint_consrc - 1] = CStringGetTextDatum(conSrc);
    else
        nulls[Anum_pg_constraint_consrc - 1] = true;

    tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);

    conOid = simple_heap_insert(conDesc, tup);

    /* update catalog indexes */
    CatalogUpdateIndexes(conDesc, tup);

    conobject.classId = ConstraintRelationId;
    conobject.objectId = conOid;
    conobject.objectSubId = 0;

    heap_close(conDesc, RowExclusiveLock);

    if (OidIsValid(relId))
    {
        /*
         * Register auto dependency from constraint to owning relation, or to
         * specific column(s) if any are mentioned.
         */
        ObjectAddress relobject;

        relobject.classId = RelationRelationId;
        relobject.objectId = relId;
        if (constraintNKeys > 0)
        {
            for (i = 0; i < constraintNKeys; i++)
            {
                relobject.objectSubId = constraintKey[i];

                recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO);
            }
        }
        else
        {
            relobject.objectSubId = 0;

            recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO);
        }
    }

    if (OidIsValid(domainId))
    {
        /*
         * Register auto dependency from constraint to owning domain
         */
        ObjectAddress domobject;

        domobject.classId = TypeRelationId;
        domobject.objectId = domainId;
        domobject.objectSubId = 0;

        recordDependencyOn(&conobject, &domobject, DEPENDENCY_AUTO);
    }

    if (OidIsValid(foreignRelId))
    {
        /*
         * Register normal dependency from constraint to foreign relation, or
         * to specific column(s) if any are mentioned.
         */
        ObjectAddress relobject;

        relobject.classId = RelationRelationId;
        relobject.objectId = foreignRelId;
        if (foreignNKeys > 0)
        {
            for (i = 0; i < foreignNKeys; i++)
            {
                relobject.objectSubId = foreignKey[i];

                recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
            }
        }
        else
        {
            relobject.objectSubId = 0;

            recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
        }
    }

    if (OidIsValid(indexRelId) && constraintType == CONSTRAINT_FOREIGN)
    {
        /*
         * Register normal dependency on the unique index that supports a
         * foreign-key constraint.  (Note: for indexes associated with unique
         * or primary-key constraints, the dependency runs the other way, and
         * is not made here.)
         */
        ObjectAddress relobject;

        relobject.classId = RelationRelationId;
        relobject.objectId = indexRelId;
        relobject.objectSubId = 0;

        recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
    }

    if (foreignNKeys > 0)
    {
        /*
         * Register normal dependencies on the equality operators that support
         * a foreign-key constraint.  If the PK and FK types are the same then
         * all three operators for a column are the same; otherwise they are
         * different.
         */
        ObjectAddress oprobject;

        oprobject.classId = OperatorRelationId;
        oprobject.objectSubId = 0;

        for (i = 0; i < foreignNKeys; i++)
        {
            oprobject.objectId = pfEqOp[i];
            recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
            if (ppEqOp[i] != pfEqOp[i])
            {
                oprobject.objectId = ppEqOp[i];
                recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
            }
            if (ffEqOp[i] != pfEqOp[i])
            {
                oprobject.objectId = ffEqOp[i];
                recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
            }
        }
    }

    /*
     * We don't bother to register dependencies on the exclusion operators of
     * an exclusion constraint.  We assume they are members of the opclass
     * supporting the index, so there's an indirect dependency via that. (This
     * would be pretty dicey for cross-type operators, but exclusion operators
     * can never be cross-type.)
     */

    if (conExpr != NULL)
    {
        /*
         * Register dependencies from constraint to objects mentioned in CHECK
         * expression.
         */
        recordDependencyOnSingleRelExpr(&conobject, conExpr, relId,
                                        DEPENDENCY_NORMAL,
                                        DEPENDENCY_NORMAL);
    }

    /* Post creation hook for new constraint */
    InvokeObjectPostCreateHookArg(ConstraintRelationId, conOid, 0,
                                  is_internal);

    return conOid;
}

Oid get_domain_constraint_oid ( Oid  typid,
const char *  conname,
bool  missing_ok 
)

Definition at line 818 of file pg_constraint.c.

References AccessShareLock, Anum_pg_constraint_contypid, BTEqualStrategyNumber, ConstraintRelationId, ConstraintTypidIndexId, ereport, errcode(), errmsg(), ERROR, format_type_be(), GETSTRUCT, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, NameStr, ObjectIdGetDatum, OidIsValid, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by rename_constraint_internal().

{
    Relation    pg_constraint;
    HeapTuple   tuple;
    SysScanDesc scan;
    ScanKeyData skey[1];
    Oid         conOid = InvalidOid;

    /*
     * Fetch the constraint tuple from pg_constraint.  There may be more than
     * one match, because constraints are not required to have unique names;
     * if so, error out.
     */
    pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);

    ScanKeyInit(&skey[0],
                Anum_pg_constraint_contypid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(typid));

    scan = systable_beginscan(pg_constraint, ConstraintTypidIndexId, true,
                              SnapshotNow, 1, skey);

    while (HeapTupleIsValid(tuple = systable_getnext(scan)))
    {
        Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);

        if (strcmp(NameStr(con->conname), conname) == 0)
        {
            if (OidIsValid(conOid))
                ereport(ERROR,
                        (errcode(ERRCODE_DUPLICATE_OBJECT),
                errmsg("domain \"%s\" has multiple constraints named \"%s\"",
                       format_type_be(typid), conname)));
            conOid = HeapTupleGetOid(tuple);
        }
    }

    systable_endscan(scan);

    /* If no such constraint exists, complain */
    if (!OidIsValid(conOid) && !missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("constraint \"%s\" for domain \"%s\" does not exist",
                        conname, format_type_be(typid))));

    heap_close(pg_constraint, AccessShareLock);

    return conOid;
}

Oid get_relation_constraint_oid ( Oid  relid,
const char *  conname,
bool  missing_ok 
)

Definition at line 760 of file pg_constraint.c.

References AccessShareLock, Anum_pg_constraint_conrelid, BTEqualStrategyNumber, ConstraintRelationId, ConstraintRelidIndexId, ereport, errcode(), errmsg(), ERROR, get_rel_name(), GETSTRUCT, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, NameStr, ObjectIdGetDatum, OidIsValid, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by get_object_address_relobject(), rename_constraint_internal(), and transformTableLikeClause().

{
    Relation    pg_constraint;
    HeapTuple   tuple;
    SysScanDesc scan;
    ScanKeyData skey[1];
    Oid         conOid = InvalidOid;

    /*
     * Fetch the constraint tuple from pg_constraint.  There may be more than
     * one match, because constraints are not required to have unique names;
     * if so, error out.
     */
    pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);

    ScanKeyInit(&skey[0],
                Anum_pg_constraint_conrelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(relid));

    scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
                              SnapshotNow, 1, skey);

    while (HeapTupleIsValid(tuple = systable_getnext(scan)))
    {
        Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);

        if (strcmp(NameStr(con->conname), conname) == 0)
        {
            if (OidIsValid(conOid))
                ereport(ERROR,
                        (errcode(ERRCODE_DUPLICATE_OBJECT),
                 errmsg("table \"%s\" has multiple constraints named \"%s\"",
                        get_rel_name(relid), conname)));
            conOid = HeapTupleGetOid(tuple);
        }
    }

    systable_endscan(scan);

    /* If no such constraint exists, complain */
    if (!OidIsValid(conOid) && !missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("constraint \"%s\" for table \"%s\" does not exist",
                        conname, get_rel_name(relid))));

    heap_close(pg_constraint, AccessShareLock);

    return conOid;
}

void RemoveConstraintById ( Oid  conId  ) 

Definition at line 533 of file pg_constraint.c.

References AccessExclusiveLock, CatalogUpdateIndexes(), CONSTRAINT_CHECK, ConstraintRelationId, CONSTROID, elog, ERROR, GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, NoLock, ObjectIdGetDatum, OidIsValid, RelationGetRelationName, RelationRelationId, ReleaseSysCache(), RELOID, RowExclusiveLock, SearchSysCache1, SearchSysCacheCopy1, simple_heap_delete(), simple_heap_update(), and HeapTupleData::t_self.

Referenced by doDeletion().

{
    Relation    conDesc;
    HeapTuple   tup;
    Form_pg_constraint con;

    conDesc = heap_open(ConstraintRelationId, RowExclusiveLock);

    tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conId));
    if (!HeapTupleIsValid(tup)) /* should not happen */
        elog(ERROR, "cache lookup failed for constraint %u", conId);
    con = (Form_pg_constraint) GETSTRUCT(tup);

    /*
     * Special processing depending on what the constraint is for.
     */
    if (OidIsValid(con->conrelid))
    {
        Relation    rel;

        /*
         * If the constraint is for a relation, open and exclusive-lock the
         * relation it's for.
         */
        rel = heap_open(con->conrelid, AccessExclusiveLock);

        /*
         * We need to update the relcheck count if it is a check constraint
         * being dropped.  This update will force backends to rebuild relcache
         * entries when we commit.
         */
        if (con->contype == CONSTRAINT_CHECK)
        {
            Relation    pgrel;
            HeapTuple   relTup;
            Form_pg_class classForm;

            pgrel = heap_open(RelationRelationId, RowExclusiveLock);
            relTup = SearchSysCacheCopy1(RELOID,
                                         ObjectIdGetDatum(con->conrelid));
            if (!HeapTupleIsValid(relTup))
                elog(ERROR, "cache lookup failed for relation %u",
                     con->conrelid);
            classForm = (Form_pg_class) GETSTRUCT(relTup);

            if (classForm->relchecks == 0)      /* should not happen */
                elog(ERROR, "relation \"%s\" has relchecks = 0",
                     RelationGetRelationName(rel));
            classForm->relchecks--;

            simple_heap_update(pgrel, &relTup->t_self, relTup);

            CatalogUpdateIndexes(pgrel, relTup);

            heap_freetuple(relTup);

            heap_close(pgrel, RowExclusiveLock);
        }

        /* Keep lock on constraint's rel until end of xact */
        heap_close(rel, NoLock);
    }
    else if (OidIsValid(con->contypid))
    {
        /*
         * XXX for now, do nothing special when dropping a domain constraint
         *
         * Probably there should be some form of locking on the domain type,
         * but we have no such concept at the moment.
         */
    }
    else
        elog(ERROR, "constraint %u is not of a known type", conId);

    /* Fry the constraint itself */
    simple_heap_delete(conDesc, &tup->t_self);

    /* Clean up */
    ReleaseSysCache(tup);
    heap_close(conDesc, RowExclusiveLock);
}

void RenameConstraintById ( Oid  conId,
const char *  newname 
)

Definition at line 626 of file pg_constraint.c.

References CatalogUpdateIndexes(), CONSTRAINT_DOMAIN, CONSTRAINT_RELATION, ConstraintNameIsUsed(), ConstraintRelationId, CONSTROID, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_rel_name(), GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, InvokeObjectPostAlterHook, namestrcpy(), ObjectIdGetDatum, OidIsValid, RowExclusiveLock, SearchSysCacheCopy1, simple_heap_update(), and HeapTupleData::t_self.

Referenced by rename_constraint_internal(), and RenameRelationInternal().

{
    Relation    conDesc;
    HeapTuple   tuple;
    Form_pg_constraint con;

    conDesc = heap_open(ConstraintRelationId, RowExclusiveLock);

    tuple = SearchSysCacheCopy1(CONSTROID, ObjectIdGetDatum(conId));
    if (!HeapTupleIsValid(tuple))
        elog(ERROR, "cache lookup failed for constraint %u", conId);
    con = (Form_pg_constraint) GETSTRUCT(tuple);

    /*
     * We need to check whether the name is already in use --- note that there
     * currently is not a unique index that would catch this.
     */
    if (OidIsValid(con->conrelid) &&
        ConstraintNameIsUsed(CONSTRAINT_RELATION,
                             con->conrelid,
                             con->connamespace,
                             newname))
        ereport(ERROR,
                (errcode(ERRCODE_DUPLICATE_OBJECT),
               errmsg("constraint \"%s\" for relation \"%s\" already exists",
                      newname, get_rel_name(con->conrelid))));
    if (OidIsValid(con->contypid) &&
        ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
                             con->contypid,
                             con->connamespace,
                             newname))
        ereport(ERROR,
                (errcode(ERRCODE_DUPLICATE_OBJECT),
                 errmsg("constraint \"%s\" for domain %s already exists",
                        newname, format_type_be(con->contypid))));

    /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
    namestrcpy(&(con->conname), newname);

    simple_heap_update(conDesc, &tuple->t_self, tuple);

    /* update the system catalog indexes */
    CatalogUpdateIndexes(conDesc, tuple);

    InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);

    heap_freetuple(tuple);
    heap_close(conDesc, RowExclusiveLock);
}