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