]> granicus.if.org Git - postgresql/blobdiff - src/backend/catalog/pg_constraint.c
Add system catalog columns pg_constraint.conindid and pg_trigger.tgconstrindid.
[postgresql] / src / backend / catalog / pg_constraint.c
index ede6607b851daed50cc1160f70f1c38af5cc0474..81c35100c7b286463081f670d47175a8e040fe11 100644 (file)
@@ -3,12 +3,12 @@
  * pg_constraint.c
  *       routines to support manipulation of the pg_constraint relation
  *
- * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.35 2007/02/14 01:58:56 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.47 2009/07/28 02:56:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #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"
 
 
 /*
@@ -46,6 +49,7 @@ CreateConstraintEntry(const char *constraintName,
                                          const int16 *constraintKey,
                                          int constraintNKeys,
                                          Oid domainId,
+                                         Oid indexRelId,
                                          Oid foreignRelId,
                                          const int16 *foreignKey,
                                          const Oid *pfEqOp,
@@ -55,15 +59,16 @@ CreateConstraintEntry(const char *constraintName,
                                          char foreignUpdateType,
                                          char foreignDeleteType,
                                          char foreignMatchType,
-                                         Oid indexRelId,
                                          Node *conExpr,
                                          const char *conBin,
-                                         const char *conSrc)
+                                         const char *conSrc,
+                                         bool conIsLocal,
+                                         int conInhCount)
 {
        Relation        conDesc;
        Oid                     conOid;
        HeapTuple       tup;
-       char            nulls[Natts_pg_constraint];
+       bool            nulls[Natts_pg_constraint];
        Datum           values[Natts_pg_constraint];
        ArrayType  *conkeyArray;
        ArrayType  *confkeyArray;
@@ -128,7 +133,7 @@ CreateConstraintEntry(const char *constraintName,
        /* initialize nulls and values */
        for (i = 0; i < Natts_pg_constraint; i++)
        {
-               nulls[i] = ' ';
+               nulls[i] = false;
                values[i] = (Datum) NULL;
        }
 
@@ -139,55 +144,56 @@ CreateConstraintEntry(const char *constraintName,
        values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred);
        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);
 
        if (conkeyArray)
                values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
        else
-               nulls[Anum_pg_constraint_conkey - 1] = 'n';
+               nulls[Anum_pg_constraint_conkey - 1] = true;
 
        if (confkeyArray)
                values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray);
        else
-               nulls[Anum_pg_constraint_confkey - 1] = 'n';
+               nulls[Anum_pg_constraint_confkey - 1] = true;
 
        if (conpfeqopArray)
                values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray);
        else
-               nulls[Anum_pg_constraint_conpfeqop - 1] = 'n';
+               nulls[Anum_pg_constraint_conpfeqop - 1] = true;
 
        if (conppeqopArray)
                values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray);
        else
-               nulls[Anum_pg_constraint_conppeqop - 1] = 'n';
+               nulls[Anum_pg_constraint_conppeqop - 1] = true;
 
        if (conffeqopArray)
                values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray);
        else
-               nulls[Anum_pg_constraint_conffeqop - 1] = 'n';
+               nulls[Anum_pg_constraint_conffeqop - 1] = true;
 
        /*
         * initialize the binary form of the check constraint.
         */
        if (conBin)
-               values[Anum_pg_constraint_conbin - 1] = DirectFunctionCall1(textin,
-                                                                                                       CStringGetDatum(conBin));
+               values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin);
        else
-               nulls[Anum_pg_constraint_conbin - 1] = 'n';
+               nulls[Anum_pg_constraint_conbin - 1] = true;
 
        /*
         * initialize the text form of the check constraint
         */
        if (conSrc)
-               values[Anum_pg_constraint_consrc - 1] = DirectFunctionCall1(textin,
-                                                                                                       CStringGetDatum(conSrc));
+               values[Anum_pg_constraint_consrc - 1] = CStringGetTextDatum(conSrc);
        else
-               nulls[Anum_pg_constraint_consrc - 1] = 'n';
+               nulls[Anum_pg_constraint_consrc - 1] = true;
 
-       tup = heap_formtuple(RelationGetDescr(conDesc), values, nulls);
+       tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);
 
        conOid = simple_heap_insert(conDesc, tup);
 
@@ -268,11 +274,13 @@ CreateConstraintEntry(const char *constraintName,
                }
        }
 
-       if (OidIsValid(indexRelId))
+       if (OidIsValid(indexRelId) && constraintType == CONSTRAINT_FOREIGN)
        {
                /*
                 * Register normal dependency on the unique index that supports a
-                * foreign-key constraint.
+                * 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;
 
@@ -286,10 +294,10 @@ CreateConstraintEntry(const char *constraintName,
        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.
+                * 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;
 
@@ -414,7 +422,7 @@ ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId,
  */
 char *
 ChooseConstraintName(const char *name1, const char *name2,
-                                        const char *label, Oid namespace,
+                                        const char *label, Oid namespaceid,
                                         List *others)
 {
        int                     pass = 0;
@@ -456,7 +464,7 @@ ChooseConstraintName(const char *name1, const char *name2,
                        ScanKeyInit(&skey[1],
                                                Anum_pg_constraint_connamespace,
                                                BTEqualStrategyNumber, F_OIDEQ,
-                                               ObjectIdGetDatum(namespace));
+                                               ObjectIdGetDatum(namespaceid));
 
                        conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
                                                                                 SnapshotNow, 2, skey);
@@ -568,6 +576,67 @@ RemoveConstraintById(Oid conId)
        heap_close(conDesc, RowExclusiveLock);
 }
 
+/*
+ * RenameConstraintById
+ *             Rename a constraint.
+ *
+ * Note: this isn't intended to be a user-exposed function; it doesn't check
+ * permissions etc.  Currently this is only invoked when renaming an index
+ * that is associated with a constraint, but it's made a little more general
+ * than that with the expectation of someday having ALTER TABLE RENAME
+ * CONSTRAINT.
+ */
+void
+RenameConstraintById(Oid conId, const char *newname)
+{
+       Relation        conDesc;
+       HeapTuple       tuple;
+       Form_pg_constraint con;
+
+       conDesc = heap_open(ConstraintRelationId, RowExclusiveLock);
+
+       tuple = SearchSysCacheCopy(CONSTROID,
+                                                          ObjectIdGetDatum(conId),
+                                                          0, 0, 0);
+       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);
+
+       heap_freetuple(tuple);
+       heap_close(conDesc, RowExclusiveLock);
+}
+
 /*
  * AlterConstraintNamespaces
  *             Find any constraints belonging to the specified object,