LCOV - differential code coverage report
Current view: top level - src/backend/catalog - pg_constraint.c (source / functions) Coverage Total Hit UNC LBC UIC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 94.8 % 498 472 3 5 18 9 245 47 171 17 281 15
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 18 18 14 4 17
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 93.0 % 43 40 3 40
Legend: Lines: hit not hit (180,240] days: 100.0 % 4 4 3 1 1
(240..) days: 94.9 % 451 428 5 18 9 242 7 170 16 250
Function coverage date bins:
[..60] days: 100.0 % 3 3 3
(240..) days: 48.4 % 31 15 14 1 16

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * pg_constraint.c
                                  4                 :  *    routines to support manipulation of the pg_constraint relation
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :  *
                                  9                 :  *
                                 10                 :  * IDENTIFICATION
                                 11                 :  *    src/backend/catalog/pg_constraint.c
                                 12                 :  *
                                 13                 :  *-------------------------------------------------------------------------
                                 14                 :  */
                                 15                 : #include "postgres.h"
                                 16                 : 
                                 17                 : #include "access/genam.h"
                                 18                 : #include "access/htup_details.h"
                                 19                 : #include "access/sysattr.h"
                                 20                 : #include "access/table.h"
                                 21                 : #include "access/xact.h"
                                 22                 : #include "catalog/catalog.h"
                                 23                 : #include "catalog/dependency.h"
                                 24                 : #include "catalog/indexing.h"
                                 25                 : #include "catalog/objectaccess.h"
                                 26                 : #include "catalog/pg_constraint.h"
                                 27                 : #include "catalog/pg_operator.h"
                                 28                 : #include "catalog/pg_type.h"
                                 29                 : #include "commands/defrem.h"
                                 30                 : #include "commands/tablecmds.h"
                                 31                 : #include "utils/array.h"
                                 32                 : #include "utils/builtins.h"
                                 33                 : #include "utils/fmgroids.h"
                                 34                 : #include "utils/lsyscache.h"
                                 35                 : #include "utils/rel.h"
                                 36                 : #include "utils/syscache.h"
                                 37                 : 
                                 38                 : 
                                 39                 : /*
                                 40                 :  * CreateConstraintEntry
                                 41                 :  *  Create a constraint table entry.
                                 42                 :  *
                                 43                 :  * Subsidiary records (such as triggers or indexes to implement the
                                 44                 :  * constraint) are *not* created here.  But we do make dependency links
                                 45                 :  * from the constraint to the things it depends on.
                                 46                 :  *
                                 47                 :  * The new constraint's OID is returned.
                                 48                 :  */
                                 49                 : Oid
 7576 tgl                        50 CBC       44635 : CreateConstraintEntry(const char *constraintName,
                                 51                 :                       Oid constraintNamespace,
                                 52                 :                       char constraintType,
                                 53                 :                       bool isDeferrable,
                                 54                 :                       bool isDeferred,
                                 55                 :                       bool isValidated,
                                 56                 :                       Oid parentConstrId,
                                 57                 :                       Oid relId,
                                 58                 :                       const int16 *constraintKey,
                                 59                 :                       int constraintNKeys,
                                 60                 :                       int constraintNTotalKeys,
                                 61                 :                       Oid domainId,
                                 62                 :                       Oid indexRelId,
                                 63                 :                       Oid foreignRelId,
                                 64                 :                       const int16 *foreignKey,
                                 65                 :                       const Oid *pfEqOp,
                                 66                 :                       const Oid *ppEqOp,
                                 67                 :                       const Oid *ffEqOp,
                                 68                 :                       int foreignNKeys,
                                 69                 :                       char foreignUpdateType,
                                 70                 :                       char foreignDeleteType,
                                 71                 :                       const int16 *fkDeleteSetCols,
                                 72                 :                       int numFkDeleteSetCols,
                                 73                 :                       char foreignMatchType,
                                 74                 :                       const Oid *exclOp,
                                 75                 :                       Node *conExpr,
                                 76                 :                       const char *conBin,
                                 77                 :                       bool conIsLocal,
                                 78                 :                       int conInhCount,
                                 79                 :                       bool conNoInherit,
                                 80                 :                       bool is_internal)
                                 81                 : {
                                 82                 :     Relation    conDesc;
                                 83                 :     Oid         conOid;
                                 84                 :     HeapTuple   tup;
                                 85                 :     bool        nulls[Natts_pg_constraint];
                                 86                 :     Datum       values[Natts_pg_constraint];
                                 87                 :     ArrayType  *conkeyArray;
                                 88                 :     ArrayType  *confkeyArray;
                                 89                 :     ArrayType  *conpfeqopArray;
                                 90                 :     ArrayType  *conppeqopArray;
                                 91                 :     ArrayType  *conffeqopArray;
                                 92                 :     ArrayType  *conexclopArray;
                                 93                 :     ArrayType  *confdelsetcolsArray;
                                 94                 :     NameData    cname;
                                 95                 :     int         i;
                                 96                 :     ObjectAddress conobject;
                                 97                 :     ObjectAddresses *addrs_auto;
                                 98                 :     ObjectAddresses *addrs_normal;
                                 99                 : 
 1539 andres                    100           44635 :     conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
                                101                 : 
 7576 tgl                       102           44635 :     Assert(constraintName);
                                103           44635 :     namestrcpy(&cname, constraintName);
                                104                 : 
                                105                 :     /*
                                106                 :      * Convert C arrays into Postgres arrays.
                                107                 :      */
                                108           44635 :     if (constraintNKeys > 0)
                                109                 :     {
                                110                 :         Datum      *conkey;
                                111                 : 
                                112           43749 :         conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum));
                                113          109970 :         for (i = 0; i < constraintNKeys; i++)
                                114           66221 :             conkey[i] = Int16GetDatum(constraintKey[i]);
  282 peter                     115 GNC       43749 :         conkeyArray = construct_array_builtin(conkey, constraintNKeys, INT2OID);
                                116                 :     }
 7576 tgl                       117 ECB             :     else
 7576 tgl                       118 GIC         886 :         conkeyArray = NULL;
 7576 tgl                       119 ECB             : 
 7576 tgl                       120 GIC       44635 :     if (foreignNKeys > 0)
                                121                 :     {
                                122                 :         Datum      *fkdatums;
 7576 tgl                       123 ECB             : 
 5898 tgl                       124 CBC        1553 :         fkdatums = (Datum *) palloc(foreignNKeys * sizeof(Datum));
 7576                           125            3445 :         for (i = 0; i < foreignNKeys; i++)
 5898                           126            1892 :             fkdatums[i] = Int16GetDatum(foreignKey[i]);
  282 peter                     127 GNC        1553 :         confkeyArray = construct_array_builtin(fkdatums, foreignNKeys, INT2OID);
 5898 tgl                       128 CBC        3445 :         for (i = 0; i < foreignNKeys; i++)
                                129            1892 :             fkdatums[i] = ObjectIdGetDatum(pfEqOp[i]);
  282 peter                     130 GNC        1553 :         conpfeqopArray = construct_array_builtin(fkdatums, foreignNKeys, OIDOID);
 5898 tgl                       131 CBC        3445 :         for (i = 0; i < foreignNKeys; i++)
                                132            1892 :             fkdatums[i] = ObjectIdGetDatum(ppEqOp[i]);
  282 peter                     133 GNC        1553 :         conppeqopArray = construct_array_builtin(fkdatums, foreignNKeys, OIDOID);
 5898 tgl                       134 CBC        3445 :         for (i = 0; i < foreignNKeys; i++)
 5898 tgl                       135 GIC        1892 :             fkdatums[i] = ObjectIdGetDatum(ffEqOp[i]);
  282 peter                     136 GNC        1553 :         conffeqopArray = construct_array_builtin(fkdatums, foreignNKeys, OIDOID);
  487 peter                     137 ECB             : 
  487 peter                     138 GIC        1553 :         if (numFkDeleteSetCols > 0)
                                139                 :         {
  487 peter                     140 CBC          60 :             for (i = 0; i < numFkDeleteSetCols; i++)
  487 peter                     141 GIC          30 :                 fkdatums[i] = Int16GetDatum(fkDeleteSetCols[i]);
  282 peter                     142 GNC          30 :             confdelsetcolsArray = construct_array_builtin(fkdatums, numFkDeleteSetCols, INT2OID);
  487 peter                     143 ECB             :         }
                                144                 :         else
  487 peter                     145 CBC        1523 :             confdelsetcolsArray = NULL;
 7576 tgl                       146 ECB             :     }
                                147                 :     else
                                148                 :     {
 7576 tgl                       149 GIC       43082 :         confkeyArray = NULL;
 5898 tgl                       150 CBC       43082 :         conpfeqopArray = NULL;
 5898 tgl                       151 GIC       43082 :         conppeqopArray = NULL;
                                152           43082 :         conffeqopArray = NULL;
  487 peter                     153           43082 :         confdelsetcolsArray = NULL;
 5898 tgl                       154 ECB             :     }
 7576                           155                 : 
 4871 tgl                       156 CBC       44635 :     if (exclOp != NULL)
 4871 tgl                       157 ECB             :     {
                                158                 :         Datum      *opdatums;
                                159                 : 
 4871 tgl                       160 CBC          64 :         opdatums = (Datum *) palloc(constraintNKeys * sizeof(Datum));
 4871 tgl                       161 GIC         143 :         for (i = 0; i < constraintNKeys; i++)
                                162              79 :             opdatums[i] = ObjectIdGetDatum(exclOp[i]);
  282 peter                     163 GNC          64 :         conexclopArray = construct_array_builtin(opdatums, constraintNKeys, OIDOID);
 4871 tgl                       164 ECB             :     }
                                165                 :     else
 4871 tgl                       166 GIC       44571 :         conexclopArray = NULL;
                                167                 : 
 7576 tgl                       168 ECB             :     /* initialize nulls and values */
 7576 tgl                       169 GIC     1205145 :     for (i = 0; i < Natts_pg_constraint; i++)
 7576 tgl                       170 ECB             :     {
 5271 tgl                       171 CBC     1160510 :         nulls[i] = false;
 7576                           172         1160510 :         values[i] = (Datum) NULL;
 7576 tgl                       173 ECB             :     }
                                174                 : 
 1601 andres                    175 CBC       44635 :     conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId,
 1601 andres                    176 ECB             :                                 Anum_pg_constraint_oid);
 1601 andres                    177 CBC       44635 :     values[Anum_pg_constraint_oid - 1] = ObjectIdGetDatum(conOid);
 7576 tgl                       178           44635 :     values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname);
                                179           44635 :     values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace);
                                180           44635 :     values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType);
                                181           44635 :     values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable);
                                182           44635 :     values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred);
 4443 simon                     183           44635 :     values[Anum_pg_constraint_convalidated - 1] = BoolGetDatum(isValidated);
 7576 tgl                       184           44635 :     values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId);
                                185           44635 :     values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId);
 5003                           186           44635 :     values[Anum_pg_constraint_conindid - 1] = ObjectIdGetDatum(indexRelId);
 1843 alvherre                  187           44635 :     values[Anum_pg_constraint_conparentid - 1] = ObjectIdGetDatum(parentConstrId);
 7576 tgl                       188 GIC       44635 :     values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId);
 7576 tgl                       189 CBC       44635 :     values[Anum_pg_constraint_confupdtype - 1] = CharGetDatum(foreignUpdateType);
                                190           44635 :     values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType);
 7576 tgl                       191 GIC       44635 :     values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType);
 5448 tgl                       192 CBC       44635 :     values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
   12 peter                     193 GNC       44635 :     values[Anum_pg_constraint_coninhcount - 1] = Int16GetDatum(conInhCount);
 4006 alvherre                  194 CBC       44635 :     values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);
 7576 tgl                       195 ECB             : 
 7576 tgl                       196 GIC       44635 :     if (conkeyArray)
 7576 tgl                       197 CBC       43749 :         values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
                                198                 :     else
 5271                           199             886 :         nulls[Anum_pg_constraint_conkey - 1] = true;
 7576 tgl                       200 ECB             : 
 7576 tgl                       201 GIC       44635 :     if (confkeyArray)
 7576 tgl                       202 CBC        1553 :         values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray);
                                203                 :     else
 5271                           204           43082 :         nulls[Anum_pg_constraint_confkey - 1] = true;
 7576 tgl                       205 ECB             : 
 5898 tgl                       206 GIC       44635 :     if (conpfeqopArray)
 5898 tgl                       207 CBC        1553 :         values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray);
                                208                 :     else
 5271                           209           43082 :         nulls[Anum_pg_constraint_conpfeqop - 1] = true;
 5898 tgl                       210 ECB             : 
 5898 tgl                       211 GIC       44635 :     if (conppeqopArray)
 5898 tgl                       212 CBC        1553 :         values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray);
                                213                 :     else
 5271                           214           43082 :         nulls[Anum_pg_constraint_conppeqop - 1] = true;
 5898 tgl                       215 ECB             : 
 5898 tgl                       216 GIC       44635 :     if (conffeqopArray)
 5898 tgl                       217 CBC        1553 :         values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray);
                                218                 :     else
 5271                           219           43082 :         nulls[Anum_pg_constraint_conffeqop - 1] = true;
 5898 tgl                       220 ECB             : 
  487 peter                     221 GIC       44635 :     if (confdelsetcolsArray)
  487 peter                     222 CBC          30 :         values[Anum_pg_constraint_confdelsetcols - 1] = PointerGetDatum(confdelsetcolsArray);
                                223                 :     else
                                224           44605 :         nulls[Anum_pg_constraint_confdelsetcols - 1] = true;
  487 peter                     225 ECB             : 
 4871 tgl                       226 GIC       44635 :     if (conexclopArray)
 4871 tgl                       227 CBC          64 :         values[Anum_pg_constraint_conexclop - 1] = PointerGetDatum(conexclopArray);
                                228                 :     else
                                229           44571 :         nulls[Anum_pg_constraint_conexclop - 1] = true;
                                230                 : 
 7576                           231           44635 :     if (conBin)
 5493 tgl                       232 GIC        1780 :         values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin);
 7576 tgl                       233 ECB             :     else
 5271 tgl                       234 GIC       42855 :         nulls[Anum_pg_constraint_conbin - 1] = true;
 7576 tgl                       235 ECB             : 
 5271 tgl                       236 GIC       44635 :     tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);
                                237                 : 
 1601 andres                    238 CBC       44635 :     CatalogTupleInsert(conDesc, tup);
                                239                 : 
 1012 michael                   240           44635 :     ObjectAddressSet(conobject, ConstraintRelationId, conOid);
                                241                 : 
 1539 andres                    242 GIC       44635 :     table_close(conDesc, RowExclusiveLock);
                                243                 : 
                                244                 :     /* Handle set of auto dependencies */
  946 michael                   245           44635 :     addrs_auto = new_object_addresses();
                                246                 : 
 7576 tgl                       247           44635 :     if (OidIsValid(relId))
 7576 tgl                       248 ECB             :     {
                                249                 :         /*
 6385 bruce                     250                 :          * Register auto dependency from constraint to owning relation, or to
                                251                 :          * specific column(s) if any are mentioned.
 7576 tgl                       252                 :          */
                                253                 :         ObjectAddress relobject;
                                254                 : 
 1828 teodor                    255 GIC       43831 :         if (constraintNTotalKeys > 0)
                                256                 :         {
                                257          110124 :             for (i = 0; i < constraintNTotalKeys; i++)
                                258                 :             {
 1012 michael                   259 CBC       66375 :                 ObjectAddressSubSet(relobject, RelationRelationId, relId,
 1012 michael                   260 ECB             :                                     constraintKey[i]);
  946 michael                   261 GIC       66375 :                 add_exact_object_address(&relobject, addrs_auto);
                                262                 :             }
                                263                 :         }
 7576 tgl                       264 ECB             :         else
                                265                 :         {
 1012 michael                   266 GIC          82 :             ObjectAddressSet(relobject, RelationRelationId, relId);
  946                           267              82 :             add_exact_object_address(&relobject, addrs_auto);
                                268                 :         }
                                269                 :     }
                                270                 : 
 7450 bruce                     271 CBC       44635 :     if (OidIsValid(domainId))
 7450 bruce                     272 ECB             :     {
                                273                 :         /*
                                274                 :          * Register auto dependency from constraint to owning domain
                                275                 :          */
                                276                 :         ObjectAddress domobject;
                                277                 : 
 1012 michael                   278 GIC         804 :         ObjectAddressSet(domobject, TypeRelationId, domainId);
  946                           279             804 :         add_exact_object_address(&domobject, addrs_auto);
 7450 bruce                     280 ECB             :     }
                                281                 : 
  946 michael                   282 CBC       44635 :     record_object_address_dependencies(&conobject, addrs_auto,
                                283                 :                                        DEPENDENCY_AUTO);
  946 michael                   284 GIC       44635 :     free_object_addresses(addrs_auto);
                                285                 : 
                                286                 :     /* Handle set of normal dependencies */
                                287           44635 :     addrs_normal = new_object_addresses();
                                288                 : 
 7576 tgl                       289           44635 :     if (OidIsValid(foreignRelId))
 7576 tgl                       290 ECB             :     {
                                291                 :         /*
 6385 bruce                     292                 :          * Register normal dependency from constraint to foreign relation, or
                                293                 :          * to specific column(s) if any are mentioned.
 7576 tgl                       294                 :          */
                                295                 :         ObjectAddress relobject;
                                296                 : 
 7576 tgl                       297 GIC        1553 :         if (foreignNKeys > 0)
                                298                 :         {
                                299            3445 :             for (i = 0; i < foreignNKeys; i++)
                                300                 :             {
 1012 michael                   301 GBC        1892 :                 ObjectAddressSubSet(relobject, RelationRelationId,
 1012 michael                   302 EUB             :                                     foreignRelId, foreignKey[i]);
  946 michael                   303 GIC        1892 :                 add_exact_object_address(&relobject, addrs_normal);
                                304                 :             }
                                305                 :         }
 7576 tgl                       306 ECB             :         else
                                307                 :         {
 1012 michael                   308 UIC           0 :             ObjectAddressSet(relobject, RelationRelationId, foreignRelId);
  946                           309               0 :             add_exact_object_address(&relobject, addrs_normal);
                                310                 :         }
                                311                 :     }
                                312                 : 
 5003 tgl                       313 GIC       44635 :     if (OidIsValid(indexRelId) && constraintType == CONSTRAINT_FOREIGN)
                                314                 :     {
                                315                 :         /*
 7188 bruce                     316 ECB             :          * Register normal dependency on the unique index that supports a
 3260                           317                 :          * foreign-key constraint.  (Note: for indexes associated with unique
                                318                 :          * or primary-key constraints, the dependency runs the other way, and
                                319                 :          * is not made here.)
 7504 tgl                       320                 :          */
                                321                 :         ObjectAddress relobject;
                                322                 : 
 1012 michael                   323 GIC        1553 :         ObjectAddressSet(relobject, RelationRelationId, indexRelId);
  946                           324            1553 :         add_exact_object_address(&relobject, addrs_normal);
                                325                 :     }
                                326                 : 
 5898 tgl                       327           44635 :     if (foreignNKeys > 0)
                                328                 :     {
                                329                 :         /*
 5624 bruce                     330 ECB             :          * Register normal dependencies on the equality operators that support
                                331                 :          * a foreign-key constraint.  If the PK and FK types are the same then
                                332                 :          * all three operators for a column are the same; otherwise they are
                                333                 :          * different.
                                334                 :          */
 5898 tgl                       335                 :         ObjectAddress oprobject;
                                336                 : 
 5898 tgl                       337 CBC        1553 :         oprobject.classId = OperatorRelationId;
 5898 tgl                       338 GIC        1553 :         oprobject.objectSubId = 0;
 5898 tgl                       339 ECB             : 
 5898 tgl                       340 CBC        3445 :         for (i = 0; i < foreignNKeys; i++)
                                341                 :         {
                                342            1892 :             oprobject.objectId = pfEqOp[i];
  946 michael                   343 GIC        1892 :             add_exact_object_address(&oprobject, addrs_normal);
 5898 tgl                       344 CBC        1892 :             if (ppEqOp[i] != pfEqOp[i])
 5898 tgl                       345 ECB             :             {
 5898 tgl                       346 GIC          28 :                 oprobject.objectId = ppEqOp[i];
  946 michael                   347              28 :                 add_exact_object_address(&oprobject, addrs_normal);
                                348                 :             }
 5898 tgl                       349            1892 :             if (ffEqOp[i] != pfEqOp[i])
 5898 tgl                       350 ECB             :             {
 5898 tgl                       351 GIC          28 :                 oprobject.objectId = ffEqOp[i];
  946 michael                   352 CBC          28 :                 add_exact_object_address(&oprobject, addrs_normal);
                                353                 :             }
                                354                 :         }
                                355                 :     }
                                356                 : 
  946 michael                   357 GIC       44635 :     record_object_address_dependencies(&conobject, addrs_normal,
                                358                 :                                        DEPENDENCY_NORMAL);
                                359           44635 :     free_object_addresses(addrs_normal);
                                360                 : 
                                361                 :     /*
 4790 bruce                     362 ECB             :      * We don't bother to register dependencies on the exclusion operators of
                                363                 :      * an exclusion constraint.  We assume they are members of the opclass
                                364                 :      * supporting the index, so there's an indirect dependency via that. (This
                                365                 :      * would be pretty dicey for cross-type operators, but exclusion operators
                                366                 :      * can never be cross-type.)
                                367                 :      */
 4871 tgl                       368                 : 
 7572 tgl                       369 GIC       44635 :     if (conExpr != NULL)
                                370                 :     {
                                371                 :         /*
                                372                 :          * Register dependencies from constraint to objects mentioned in CHECK
                                373                 :          * expression.
 7572 tgl                       374 ECB             :          */
 7256 tgl                       375 GIC        1780 :         recordDependencyOnSingleRelExpr(&conobject, conExpr, relId,
                                376                 :                                         DEPENDENCY_NORMAL,
  702 tmunro                    377 ECB             :                                         DEPENDENCY_NORMAL, false);
                                378                 :     }
                                379                 : 
                                380                 :     /* Post creation hook for new constraint */
 3675 rhaas                     381 GIC       44635 :     InvokeObjectPostCreateHookArg(ConstraintRelationId, conOid, 0,
                                382                 :                                   is_internal);
                                383                 : 
 7576 tgl                       384           44635 :     return conOid;
                                385                 : }
                                386                 : 
                                387                 : /*
                                388                 :  * Test whether given name is currently used as a constraint name
                                389                 :  * for the given object (relation or domain).
                                390                 :  *
                                391                 :  * This is used to decide whether to accept a user-specified constraint name.
                                392                 :  * It is deliberately not the same test as ChooseConstraintName uses to decide
 6877 tgl                       393 ECB             :  * whether an auto-generated name is OK: here, we will allow it unless there
                                394                 :  * is an identical constraint name in use *on the same object*.
                                395                 :  *
                                396                 :  * NB: Caller should hold exclusive lock on the given object, else
                                397                 :  * this test can be fooled by concurrent additions.
                                398                 :  */
                                399                 : bool
 6877 tgl                       400 GIC        6881 : ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId,
 1678 tgl                       401 ECB             :                      const char *conname)
                                402                 : {
 7576                           403                 :     bool        found;
                                404                 :     Relation    conDesc;
                                405                 :     SysScanDesc conscan;
                                406                 :     ScanKeyData skey[3];
                                407                 : 
 1539 andres                    408 CBC        6881 :     conDesc = table_open(ConstraintRelationId, AccessShareLock);
                                409                 : 
 1678 tgl                       410 GIC        6881 :     ScanKeyInit(&skey[0],
                                411                 :                 Anum_pg_constraint_conrelid,
                                412                 :                 BTEqualStrategyNumber, F_OIDEQ,
 1678 tgl                       413 ECB             :                 ObjectIdGetDatum((conCat == CONSTRAINT_RELATION)
                                414                 :                                  ? objId : InvalidOid));
 1678 tgl                       415 GIC        6881 :     ScanKeyInit(&skey[1],
                                416                 :                 Anum_pg_constraint_contypid,
                                417                 :                 BTEqualStrategyNumber, F_OIDEQ,
 1678 tgl                       418 ECB             :                 ObjectIdGetDatum((conCat == CONSTRAINT_DOMAIN)
                                419                 :                                  ? objId : InvalidOid));
 1678 tgl                       420 GIC        6881 :     ScanKeyInit(&skey[2],
                                421                 :                 Anum_pg_constraint_conname,
 1678 tgl                       422 ECB             :                 BTEqualStrategyNumber, F_NAMEEQ,
                                423                 :                 CStringGetDatum(conname));
                                424                 : 
 1678 tgl                       425 CBC        6881 :     conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId,
                                426                 :                                  true, NULL, 3, skey);
 1678 tgl                       427 ECB             : 
                                428                 :     /* There can be at most one matching row */
 1678 tgl                       429 GIC        6881 :     found = (HeapTupleIsValid(systable_getnext(conscan)));
                                430                 : 
                                431            6881 :     systable_endscan(conscan);
 1539 andres                    432            6881 :     table_close(conDesc, AccessShareLock);
                                433                 : 
 1678 tgl                       434            6881 :     return found;
                                435                 : }
                                436                 : 
                                437                 : /*
 1678 tgl                       438 ECB             :  * Does any constraint of the given name exist in the given namespace?
                                439                 :  *
                                440                 :  * This is used for code that wants to match ChooseConstraintName's rule
                                441                 :  * that we should avoid autogenerating duplicate constraint names within a
                                442                 :  * namespace.
                                443                 :  */
                                444                 : bool
 1678 tgl                       445 CBC        3840 : ConstraintNameExists(const char *conname, Oid namespaceid)
                                446                 : {
 1678 tgl                       447 ECB             :     bool        found;
                                448                 :     Relation    conDesc;
                                449                 :     SysScanDesc conscan;
                                450                 :     ScanKeyData skey[2];
                                451                 : 
 1539 andres                    452 CBC        3840 :     conDesc = table_open(ConstraintRelationId, AccessShareLock);
                                453                 : 
 7088 tgl                       454 GIC        3840 :     ScanKeyInit(&skey[0],
                                455                 :                 Anum_pg_constraint_conname,
                                456                 :                 BTEqualStrategyNumber, F_NAMEEQ,
 6877 tgl                       457 ECB             :                 CStringGetDatum(conname));
                                458                 : 
 7088 tgl                       459 GIC        3840 :     ScanKeyInit(&skey[1],
 7088 tgl                       460 ECB             :                 Anum_pg_constraint_connamespace,
                                461                 :                 BTEqualStrategyNumber, F_OIDEQ,
 1678                           462                 :                 ObjectIdGetDatum(namespaceid));
 7576                           463                 : 
 6569 tgl                       464 GIC        3840 :     conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
 3568 rhaas                     465 ECB             :                                  NULL, 2, skey);
                                466                 : 
 1678 tgl                       467 GIC        3840 :     found = (HeapTupleIsValid(systable_getnext(conscan)));
                                468                 : 
 7576                           469            3840 :     systable_endscan(conscan);
 1539 andres                    470            3840 :     table_close(conDesc, AccessShareLock);
                                471                 : 
 7576 tgl                       472            3840 :     return found;
                                473                 : }
                                474                 : 
                                475                 : /*
                                476                 :  * Select a nonconflicting name for a new constraint.
                                477                 :  *
                                478                 :  * The objective here is to choose a name that is unique within the
                                479                 :  * specified namespace.  Postgres does not require this, but the SQL
                                480                 :  * spec does, and some apps depend on it.  Therefore we avoid choosing
                                481                 :  * default names that so conflict.
                                482                 :  *
                                483                 :  * name1, name2, and label are used the same way as for makeObjectName(),
                                484                 :  * except that the label can't be NULL; digits will be appended to the label
                                485                 :  * if needed to create a name that is unique within the specified namespace.
                                486                 :  *
                                487                 :  * 'others' can be a list of string names already chosen within the current
                                488                 :  * command (but not yet reflected into the catalogs); we will not choose
                                489                 :  * a duplicate of one of these either.
                                490                 :  *
                                491                 :  * Note: it is theoretically possible to get a collision anyway, if someone
 6877 tgl                       492 ECB             :  * else chooses the same name concurrently.  This is fairly unlikely to be
                                493                 :  * a problem in practice, especially if one is holding an exclusive lock on
                                494                 :  * the relation identified by name1.
                                495                 :  *
                                496                 :  * Returns a palloc'd string.
 7576                           497                 :  */
                                498                 : char *
 6877 tgl                       499 GIC        4637 : ChooseConstraintName(const char *name1, const char *name2,
                                500                 :                      const char *label, Oid namespaceid,
                                501                 :                      List *others)
                                502                 : {
                                503            4637 :     int         pass = 0;
                                504            4637 :     char       *conname = NULL;
 6877 tgl                       505 ECB             :     char        modlabel[NAMEDATALEN];
                                506                 :     Relation    conDesc;
                                507                 :     SysScanDesc conscan;
                                508                 :     ScanKeyData skey[2];
                                509                 :     bool        found;
                                510                 :     ListCell   *l;
                                511                 : 
 1539 andres                    512 CBC        4637 :     conDesc = table_open(ConstraintRelationId, AccessShareLock);
                                513                 : 
 6877 tgl                       514 ECB             :     /* try the unmodified label first */
  972 peter                     515 GIC        4637 :     strlcpy(modlabel, label, sizeof(modlabel));
 7576 tgl                       516 ECB             : 
                                517                 :     for (;;)
                                518                 :     {
 6877 tgl                       519 GIC        5400 :         conname = makeObjectName(name1, name2, modlabel);
 7576 tgl                       520 ECB             : 
 7576 tgl                       521 CBC        5400 :         found = false;
                                522                 : 
 6877 tgl                       523 GIC        6603 :         foreach(l, others)
                                524                 :         {
 6877 tgl                       525 CBC        1212 :             if (strcmp((char *) lfirst(l), conname) == 0)
                                526                 :             {
 7576                           527               9 :                 found = true;
 7576 tgl                       528 GIC           9 :                 break;
                                529                 :             }
                                530                 :         }
                                531                 : 
 6877 tgl                       532 CBC        5400 :         if (!found)
                                533                 :         {
 6877 tgl                       534 GIC        5391 :             ScanKeyInit(&skey[0],
                                535                 :                         Anum_pg_constraint_conname,
                                536                 :                         BTEqualStrategyNumber, F_NAMEEQ,
 6877 tgl                       537 ECB             :                         CStringGetDatum(conname));
                                538                 : 
 6877 tgl                       539 GIC        5391 :             ScanKeyInit(&skey[1],
 6877 tgl                       540 ECB             :                         Anum_pg_constraint_connamespace,
                                541                 :                         BTEqualStrategyNumber, F_OIDEQ,
 5015 peter_e                   542                 :                         ObjectIdGetDatum(namespaceid));
                                543                 : 
 6569 tgl                       544 GIC        5391 :             conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
 3568 rhaas                     545 ECB             :                                          NULL, 2, skey);
 7576 tgl                       546                 : 
 6877 tgl                       547 GIC        5391 :             found = (HeapTupleIsValid(systable_getnext(conscan)));
                                548                 : 
 6877 tgl                       549 CBC        5391 :             systable_endscan(conscan);
 6877 tgl                       550 ECB             :         }
                                551                 : 
 6877 tgl                       552 GIC        5400 :         if (!found)
 6877 tgl                       553 CBC        4637 :             break;
                                554                 : 
 6877 tgl                       555 ECB             :         /* found a conflict, so try a new name component */
 6877 tgl                       556 GIC         763 :         pfree(conname);
                                557             763 :         snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
                                558                 :     }
                                559                 : 
 1539 andres                    560            4637 :     table_close(conDesc, AccessShareLock);
                                561                 : 
 6877 tgl                       562            4637 :     return conname;
                                563                 : }
                                564                 : 
                                565                 : /*
                                566                 :  * Find and return the pg_constraint tuple that implements a validated
                                567                 :  * NOT NULL constraint for the given column of the given relation.
                                568                 :  *
                                569                 :  * XXX This would be easier if we had pg_attribute.notnullconstr with the OID
                                570                 :  * of the constraint that implements the NOT NULL constraint for that column.
                                571                 :  * I'm not sure it's worth the catalog bloat and de-normalization, however.
                                572                 :  */
                                573                 : HeapTuple
    2 alvherre                  574 GNC         221 : findNotNullConstraintAttnum(Relation rel, AttrNumber attnum)
                                575                 : {
                                576                 :     Relation    pg_constraint;
                                577                 :     HeapTuple   conTup,
                                578             221 :                 retval = NULL;
                                579                 :     SysScanDesc scan;
                                580                 :     ScanKeyData key;
                                581                 : 
                                582             221 :     pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
                                583             221 :     ScanKeyInit(&key,
                                584                 :                 Anum_pg_constraint_conrelid,
                                585                 :                 BTEqualStrategyNumber, F_OIDEQ,
                                586                 :                 ObjectIdGetDatum(RelationGetRelid(rel)));
                                587             221 :     scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
                                588                 :                               true, NULL, 1, &key);
                                589                 : 
                                590             394 :     while (HeapTupleIsValid(conTup = systable_getnext(scan)))
                                591                 :     {
                                592             259 :         Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(conTup);
                                593                 :         AttrNumber  conkey;
                                594                 : 
                                595                 :         /*
                                596                 :          * We're looking for a NOTNULL constraint that's marked validated,
                                597                 :          * with the column we're looking for as the sole element in conkey.
                                598                 :          */
                                599             259 :         if (con->contype != CONSTRAINT_NOTNULL)
                                600              76 :             continue;
                                601             183 :         if (!con->convalidated)
    2 alvherre                  602 UNC           0 :             continue;
                                603                 : 
    2 alvherre                  604 GNC         183 :         conkey = extractNotNullColumn(conTup);
                                605             183 :         if (conkey != attnum)
                                606              97 :             continue;
                                607                 : 
                                608                 :         /* Found it */
                                609              86 :         retval = heap_copytuple(conTup);
                                610              86 :         break;
                                611                 :     }
                                612                 : 
                                613             221 :     systable_endscan(scan);
                                614             221 :     table_close(pg_constraint, AccessShareLock);
                                615                 : 
                                616             221 :     return retval;
                                617                 : }
                                618                 : 
                                619                 : /*
                                620                 :  * Find and return the pg_constraint tuple that implements a validated
                                621                 :  * NOT NULL constraint for the given column of the given relation.
                                622                 :  */
                                623                 : HeapTuple
                                624              80 : findNotNullConstraint(Relation rel, const char *colname)
                                625                 : {
                                626              80 :     AttrNumber  attnum = get_attnum(RelationGetRelid(rel), colname);
                                627                 : 
                                628              80 :     return findNotNullConstraintAttnum(rel, attnum);
                                629                 : }
                                630                 : 
                                631                 : /*
                                632                 :  * Given a pg_constraint tuple for a NOT NULL constraint, return the column
                                633                 :  * number it is for.
                                634                 :  */
                                635                 : AttrNumber
                                636            1397 : extractNotNullColumn(HeapTuple constrTup)
                                637                 : {
                                638                 :     AttrNumber  colnum;
                                639                 :     Datum       adatum;
                                640                 :     ArrayType  *arr;
                                641                 : 
                                642                 :     /* only tuples for CHECK constraints should be given */
                                643            1397 :     Assert(((Form_pg_constraint) GETSTRUCT(constrTup))->contype == CONSTRAINT_NOTNULL);
                                644                 : 
                                645            1397 :     adatum = SysCacheGetAttrNotNull(CONSTROID, constrTup,
                                646                 :                                     Anum_pg_constraint_conkey);
                                647            1397 :     arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
                                648            1397 :     if (ARR_NDIM(arr) != 1 ||
                                649            1397 :         ARR_HASNULL(arr) ||
                                650            1397 :         ARR_ELEMTYPE(arr) != INT2OID ||
                                651            1397 :         ARR_DIMS(arr)[0] != 1)
    2 alvherre                  652 UNC           0 :         elog(ERROR, "conkey is not a 1-D smallint array");
                                653                 : 
    2 alvherre                  654 GNC        1397 :     memcpy(&colnum, ARR_DATA_PTR(arr), sizeof(AttrNumber));
                                655                 : 
                                656            1397 :     if ((Pointer) arr != DatumGetPointer(adatum))
                                657            1397 :         pfree(arr);             /* free de-toasted copy, if any */
                                658                 : 
                                659            1397 :     return colnum;
                                660                 : }
                                661                 : 
                                662                 : /*
                                663                 :  * Delete a single constraint record.
 7576 tgl                       664 ECB             :  */
                                665                 : void
 7576 tgl                       666 GIC        8799 : RemoveConstraintById(Oid conId)
                                667                 : {
 7522 bruce                     668 ECB             :     Relation    conDesc;
                                669                 :     HeapTuple   tup;
                                670                 :     Form_pg_constraint con;
                                671                 : 
 1539 andres                    672 CBC        8799 :     conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
 7576 tgl                       673 ECB             : 
 4802 rhaas                     674 GIC        8799 :     tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conId));
 5898 tgl                       675            8799 :     if (!HeapTupleIsValid(tup)) /* should not happen */
 5898 tgl                       676 UIC           0 :         elog(ERROR, "cache lookup failed for constraint %u", conId);
 7576 tgl                       677 CBC        8799 :     con = (Form_pg_constraint) GETSTRUCT(tup);
                                678                 : 
                                679                 :     /*
 7423 tgl                       680 ECB             :      * Special processing depending on what the constraint is for.
                                681                 :      */
 7576 tgl                       682 CBC        8799 :     if (OidIsValid(con->conrelid))
                                683                 :     {
                                684                 :         Relation    rel;
                                685                 : 
                                686                 :         /*
                                687                 :          * If the constraint is for a relation, open and exclusive-lock the
                                688                 :          * relation it's for.
 7423 tgl                       689 ECB             :          */
 1539 andres                    690 CBC        8686 :         rel = table_open(con->conrelid, AccessExclusiveLock);
 7576 tgl                       691 ECB             : 
 7576 tgl                       692 EUB             :         /*
                                693                 :          * We need to update the relchecks count if it is a check constraint
 6385 bruce                     694 ECB             :          * being dropped.  This update will force backends to rebuild relcache
                                695                 :          * entries when we commit.
 7576 tgl                       696                 :          */
 7576 tgl                       697 GIC        8685 :         if (con->contype == CONSTRAINT_CHECK)
                                698                 :         {
 7522 bruce                     699 ECB             :             Relation    pgrel;
                                700                 :             HeapTuple   relTup;
                                701                 :             Form_pg_class classForm;
                                702                 : 
 1539 andres                    703 CBC         758 :             pgrel = table_open(RelationRelationId, RowExclusiveLock);
 4802 rhaas                     704             758 :             relTup = SearchSysCacheCopy1(RELOID,
                                705                 :                                          ObjectIdGetDatum(con->conrelid));
 7576 tgl                       706             758 :             if (!HeapTupleIsValid(relTup))
 7202 tgl                       707 UIC           0 :                 elog(ERROR, "cache lookup failed for relation %u",
                                708                 :                      con->conrelid);
 7576 tgl                       709 GIC         758 :             classForm = (Form_pg_class) GETSTRUCT(relTup);
                                710                 : 
 2118                           711             758 :             if (classForm->relchecks == 0)   /* should not happen */
 7202 tgl                       712 UIC           0 :                 elog(ERROR, "relation \"%s\" has relchecks = 0",
                                713                 :                      RelationGetRelationName(rel));
 7576 tgl                       714 CBC         758 :             classForm->relchecks--;
                                715                 : 
 2259 alvherre                  716             758 :             CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
                                717                 : 
 7576 tgl                       718             758 :             heap_freetuple(relTup);
                                719                 : 
 1539 andres                    720 GIC         758 :             table_close(pgrel, RowExclusiveLock);
                                721                 :         }
                                722                 : 
                                723                 :         /* Keep lock on constraint's rel until end of xact */
                                724            8685 :         table_close(rel, NoLock);
                                725                 :     }
 7450 bruce                     726 CBC         113 :     else if (OidIsValid(con->contypid))
                                727                 :     {
                                728                 :         /*
                                729                 :          * XXX for now, do nothing special when dropping a domain constraint
                                730                 :          *
                                731                 :          * Probably there should be some form of locking on the domain type,
                                732                 :          * but we have no such concept at the moment.
 7423 tgl                       733 ECB             :          */
                                734                 :     }
 7429 bruce                     735                 :     else
 7202 tgl                       736 UIC           0 :         elog(ERROR, "constraint %u is not of a known type", conId);
 7576 tgl                       737 ECB             : 
                                738                 :     /* Fry the constraint itself */
 2258 tgl                       739 CBC        8798 :     CatalogTupleDelete(conDesc, &tup->t_self);
 7576 tgl                       740 ECB             : 
                                741                 :     /* Clean up */
 5898 tgl                       742 GBC        8798 :     ReleaseSysCache(tup);
 1539 andres                    743 GIC        8798 :     table_close(conDesc, RowExclusiveLock);
 7576 tgl                       744 CBC        8798 : }
                                745                 : 
 5561 tgl                       746 ECB             : /*
                                747                 :  * RenameConstraintById
                                748                 :  *      Rename a constraint.
                                749                 :  *
                                750                 :  * Note: this isn't intended to be a user-exposed function; it doesn't check
                                751                 :  * permissions etc.  Currently this is only invoked when renaming an index
                                752                 :  * that is associated with a constraint, but it's made a little more general
                                753                 :  * than that with the expectation of someday having ALTER TABLE RENAME
                                754                 :  * CONSTRAINT.
                                755                 :  */
                                756                 : void
 5561 tgl                       757 GIC          45 : RenameConstraintById(Oid conId, const char *newname)
                                758                 : {
                                759                 :     Relation    conDesc;
                                760                 :     HeapTuple   tuple;
                                761                 :     Form_pg_constraint con;
 5561 tgl                       762 ECB             : 
 1539 andres                    763 GIC          45 :     conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
 5561 tgl                       764 ECB             : 
 4802 rhaas                     765 CBC          45 :     tuple = SearchSysCacheCopy1(CONSTROID, ObjectIdGetDatum(conId));
 5561 tgl                       766 GBC          45 :     if (!HeapTupleIsValid(tuple))
 5561 tgl                       767 LBC           0 :         elog(ERROR, "cache lookup failed for constraint %u", conId);
 5561 tgl                       768 GIC          45 :     con = (Form_pg_constraint) GETSTRUCT(tuple);
                                769                 : 
                                770                 :     /*
                                771                 :      * For user-friendliness, check whether the name is already in use.
 5561 tgl                       772 ECB             :      */
 5561 tgl                       773 GIC          87 :     if (OidIsValid(con->conrelid) &&
                                774              42 :         ConstraintNameIsUsed(CONSTRAINT_RELATION,
                                775                 :                              con->conrelid,
                                776                 :                              newname))
 5561 tgl                       777 UIC           0 :         ereport(ERROR,
                                778                 :                 (errcode(ERRCODE_DUPLICATE_OBJECT),
                                779                 :                  errmsg("constraint \"%s\" for relation \"%s\" already exists",
 2118 tgl                       780 ECB             :                         newname, get_rel_name(con->conrelid))));
 5561 tgl                       781 GIC          48 :     if (OidIsValid(con->contypid) &&
                                782               3 :         ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
                                783                 :                              con->contypid,
                                784                 :                              newname))
 5561 tgl                       785 UIC           0 :         ereport(ERROR,
                                786                 :                 (errcode(ERRCODE_DUPLICATE_OBJECT),
 4093 peter_e                   787 ECB             :                  errmsg("constraint \"%s\" for domain %s already exists",
                                788                 :                         newname, format_type_be(con->contypid))));
                                789                 : 
                                790                 :     /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
 5561 tgl                       791 GIC          45 :     namestrcpy(&(con->conname), newname);
                                792                 : 
 2259 alvherre                  793 CBC          45 :     CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
 5561 tgl                       794 ECB             : 
 3675 rhaas                     795 GIC          45 :     InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
 3675 rhaas                     796 ECB             : 
 5561 tgl                       797 GBC          45 :     heap_freetuple(tuple);
 1539 andres                    798 GIC          45 :     table_close(conDesc, RowExclusiveLock);
 5561 tgl                       799 CBC          45 : }
                                800                 : 
 6460 tgl                       801 ECB             : /*
 6460 tgl                       802 EUB             :  * AlterConstraintNamespaces
                                803                 :  *      Find any constraints belonging to the specified object,
 6460 tgl                       804 ECB             :  *      and move them to the specified new namespace.
                                805                 :  *
                                806                 :  * isType indicates whether the owning object is a type or a relation.
                                807                 :  */
                                808                 : void
 6460 tgl                       809 GIC          44 : AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
 2118 tgl                       810 ECB             :                           Oid newNspId, bool isType, ObjectAddresses *objsMoved)
                                811                 : {
                                812                 :     Relation    conRel;
                                813                 :     ScanKeyData key[2];
 6385 bruce                     814                 :     SysScanDesc scan;
                                815                 :     HeapTuple   tup;
 6460 tgl                       816                 : 
 1539 andres                    817 GIC          44 :     conRel = table_open(ConstraintRelationId, RowExclusiveLock);
                                818                 : 
 1678 tgl                       819              44 :     ScanKeyInit(&key[0],
                                820                 :                 Anum_pg_constraint_conrelid,
                                821                 :                 BTEqualStrategyNumber, F_OIDEQ,
                                822                 :                 ObjectIdGetDatum(isType ? InvalidOid : ownerId));
                                823              44 :     ScanKeyInit(&key[1],
                                824                 :                 Anum_pg_constraint_contypid,
                                825                 :                 BTEqualStrategyNumber, F_OIDEQ,
 1678 tgl                       826 EUB             :                 ObjectIdGetDatum(isType ? ownerId : InvalidOid));
                                827                 : 
 1678 tgl                       828 GIC          44 :     scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
 1678 tgl                       829 ECB             :                               NULL, 2, key);
                                830                 : 
 6460 tgl                       831 GIC          96 :     while (HeapTupleIsValid((tup = systable_getnext(scan))))
 6460 tgl                       832 ECB             :     {
 6460 tgl                       833 CBC          52 :         Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(tup);
 3602 bruce                     834 ECB             :         ObjectAddress thisobj;
                                835                 : 
 1012 michael                   836 GIC          52 :         ObjectAddressSet(thisobj, ConstraintRelationId, conform->oid);
                                837                 : 
 3812 alvherre                  838              52 :         if (object_address_present(&thisobj, objsMoved))
 3812 alvherre                  839 UIC           0 :             continue;
                                840                 : 
                                841                 :         /* Don't update if the object is already part of the namespace */
 2698 rhaas                     842 GIC          52 :         if (conform->connamespace == oldNspId && oldNspId != newNspId)
                                843                 :         {
 6460 tgl                       844              37 :             tup = heap_copytuple(tup);
                                845              37 :             conform = (Form_pg_constraint) GETSTRUCT(tup);
                                846                 : 
 6460 tgl                       847 CBC          37 :             conform->connamespace = newNspId;
                                848                 : 
 2259 alvherre                  849 GIC          37 :             CatalogTupleUpdate(conRel, &tup->t_self, tup);
                                850                 : 
                                851                 :             /*
                                852                 :              * Note: currently, the constraint will not have its own
 6460 tgl                       853 ECB             :              * dependency on the namespace, so we don't need to do
                                854                 :              * changeDependencyFor().
                                855                 :              */
                                856                 :         }
 3812 alvherre                  857 EUB             : 
 3675 rhaas                     858 CBC          52 :         InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
                                859                 : 
 3812 alvherre                  860 GIC          52 :         add_exact_object_address(&thisobj, objsMoved);
                                861                 :     }
                                862                 : 
 6460 tgl                       863 CBC          44 :     systable_endscan(scan);
 6460 tgl                       864 ECB             : 
 1539 andres                    865 GIC          44 :     table_close(conRel, RowExclusiveLock);
 6460 tgl                       866              44 : }
 4927 andrew                    867 EUB             : 
                                868                 : /*
                                869                 :  * ConstraintSetParentConstraint
                                870                 :  *      Set a partition's constraint as child of its parent constraint,
 1518 tgl                       871 ECB             :  *      or remove the linkage if parentConstrId is InvalidOid.
 1875 alvherre                  872                 :  *
                                873                 :  * This updates the constraint's pg_constraint row to show it as inherited, and
                                874                 :  * adds PARTITION dependencies to prevent the constraint from being deleted
 1518 tgl                       875 EUB             :  * on its own.  Alternatively, reverse that.
                                876                 :  */
                                877                 : void
 1518 tgl                       878 GIC         222 : ConstraintSetParentConstraint(Oid childConstrId,
                                879                 :                               Oid parentConstrId,
                                880                 :                               Oid childTableId)
 1875 alvherre                  881 ECB             : {
                                882                 :     Relation    constrRel;
                                883                 :     Form_pg_constraint constrForm;
                                884                 :     HeapTuple   tuple,
 1809 tgl                       885                 :                 newtup;
                                886                 :     ObjectAddress depender;
                                887                 :     ObjectAddress referenced;
 1875 alvherre                  888                 : 
 1539 andres                    889 CBC         222 :     constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
 1875 alvherre                  890 GIC         222 :     tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
                                891             222 :     if (!HeapTupleIsValid(tuple))
 1875 alvherre                  892 UIC           0 :         elog(ERROR, "cache lookup failed for constraint %u", childConstrId);
 1875 alvherre                  893 GIC         222 :     newtup = heap_copytuple(tuple);
                                894             222 :     constrForm = (Form_pg_constraint) GETSTRUCT(newtup);
 1640                           895             222 :     if (OidIsValid(parentConstrId))
                                896                 :     {
                                897                 :         /* don't allow setting parent for a constraint that already has one */
 1536                           898             143 :         Assert(constrForm->coninhcount == 0);
 1536 alvherre                  899 CBC         143 :         if (constrForm->conparentid != InvalidOid)
 1536 alvherre                  900 UIC           0 :             elog(ERROR, "constraint %u already has a parent constraint",
                                901                 :                  childConstrId);
                                902                 : 
 1640 alvherre                  903 GIC         143 :         constrForm->conislocal = false;
                                904             143 :         constrForm->coninhcount++;
   12 peter                     905 GNC         143 :         if (constrForm->coninhcount < 0)
   12 peter                     906 UNC           0 :             ereport(ERROR,
                                907                 :                     errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                908                 :                     errmsg("too many inheritance parents"));
 1640 alvherre                  909 GIC         143 :         constrForm->conparentid = parentConstrId;
                                910                 : 
 1640 alvherre                  911 CBC         143 :         CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
                                912                 : 
                                913             143 :         ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
                                914                 : 
 1518 tgl                       915 GIC         143 :         ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
                                916             143 :         recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
 1518 tgl                       917 ECB             : 
 1518 tgl                       918 GIC         143 :         ObjectAddressSet(referenced, RelationRelationId, childTableId);
                                919             143 :         recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
                                920                 :     }
                                921                 :     else
 1640 alvherre                  922 ECB             :     {
 1640 alvherre                  923 GIC          79 :         constrForm->coninhcount--;
 1536                           924              79 :         constrForm->conislocal = true;
 1640 alvherre                  925 CBC          79 :         constrForm->conparentid = InvalidOid;
                                926                 : 
 1536 alvherre                  927 ECB             :         /* Make sure there's no further inheritance. */
 1536 alvherre                  928 GIC          79 :         Assert(constrForm->coninhcount == 0);
                                929                 : 
 1518 tgl                       930 CBC          79 :         CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
                                931                 : 
 1640 alvherre                  932              79 :         deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
 1640 alvherre                  933 EUB             :                                         ConstraintRelationId,
                                934                 :                                         DEPENDENCY_PARTITION_PRI);
 1518 tgl                       935 GIC          79 :         deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
 1518 tgl                       936 ECB             :                                         RelationRelationId,
                                937                 :                                         DEPENDENCY_PARTITION_SEC);
 1640 alvherre                  938                 :     }
 1875                           939                 : 
 1640 alvherre                  940 GIC         222 :     ReleaseSysCache(tuple);
 1539 andres                    941 CBC         222 :     table_close(constrRel, RowExclusiveLock);
 1875 alvherre                  942 GIC         222 : }
 1875 alvherre                  943 ECB             : 
                                944                 : 
                                945                 : /*
                                946                 :  * get_relation_constraint_oid
                                947                 :  *      Find a constraint on the specified relation with the specified name.
                                948                 :  *      Returns constraint's OID.
                                949                 :  */
                                950                 : Oid
 4023 peter_e                   951 GIC         160 : get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
 4927 andrew                    952 ECB             : {
                                953                 :     Relation    pg_constraint;
                                954                 :     HeapTuple   tuple;
                                955                 :     SysScanDesc scan;
                                956                 :     ScanKeyData skey[3];
 4927 andrew                    957 CBC         160 :     Oid         conOid = InvalidOid;
                                958                 : 
 1539 andres                    959             160 :     pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
 4927 andrew                    960 ECB             : 
 4927 andrew                    961 GIC         160 :     ScanKeyInit(&skey[0],
                                962                 :                 Anum_pg_constraint_conrelid,
                                963                 :                 BTEqualStrategyNumber, F_OIDEQ,
                                964                 :                 ObjectIdGetDatum(relid));
 1678 tgl                       965             160 :     ScanKeyInit(&skey[1],
                                966                 :                 Anum_pg_constraint_contypid,
                                967                 :                 BTEqualStrategyNumber, F_OIDEQ,
                                968                 :                 ObjectIdGetDatum(InvalidOid));
                                969             160 :     ScanKeyInit(&skey[2],
                                970                 :                 Anum_pg_constraint_conname,
                                971                 :                 BTEqualStrategyNumber, F_NAMEEQ,
 1678 tgl                       972 ECB             :                 CStringGetDatum(conname));
                                973                 : 
 1678 tgl                       974 GIC         160 :     scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
                                975                 :                               NULL, 3, skey);
                                976                 : 
                                977                 :     /* There can be at most one matching row */
                                978             160 :     if (HeapTupleIsValid(tuple = systable_getnext(scan)))
 1601 andres                    979             154 :         conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
                                980                 : 
 4927 andrew                    981             160 :     systable_endscan(scan);
                                982                 : 
 4926 tgl                       983 ECB             :     /* If no such constraint exists, complain */
 4630 rhaas                     984 CBC         160 :     if (!OidIsValid(conOid) && !missing_ok)
 4927 andrew                    985               6 :         ereport(ERROR,
 4927 andrew                    986 EUB             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
 4927 andrew                    987 ECB             :                  errmsg("constraint \"%s\" for table \"%s\" does not exist",
 4926 tgl                       988                 :                         conname, get_rel_name(relid))));
 4927 andrew                    989                 : 
 1539 andres                    990 GIC         154 :     table_close(pg_constraint, AccessShareLock);
                                991                 : 
 4927 andrew                    992 CBC         154 :     return conOid;
 4927 andrew                    993 ECB             : }
 4628 tgl                       994 EUB             : 
                                995                 : /*
                                996                 :  * get_relation_constraint_attnos
 1980 dean.a.rasheed            997 ECB             :  *      Find a constraint on the specified relation with the specified name
                                998                 :  *      and return the constrained columns.
                                999                 :  *
 1980 dean.a.rasheed           1000 EUB             :  * Returns a Bitmapset of the column attnos of the constrained columns, with
                               1001                 :  * attnos being offset by FirstLowInvalidHeapAttributeNumber so that system
                               1002                 :  * columns can be represented.
 1980 dean.a.rasheed           1003 ECB             :  *
                               1004                 :  * *constraintOid is set to the OID of the constraint, or InvalidOid on
                               1005                 :  * failure.
                               1006                 :  */
                               1007                 : Bitmapset *
 1980 dean.a.rasheed           1008 GIC          24 : get_relation_constraint_attnos(Oid relid, const char *conname,
 1980 dean.a.rasheed           1009 ECB             :                                bool missing_ok, Oid *constraintOid)
                               1010                 : {
 1980 dean.a.rasheed           1011 GIC          24 :     Bitmapset  *conattnos = NULL;
 1980 dean.a.rasheed           1012 ECB             :     Relation    pg_constraint;
                               1013                 :     HeapTuple   tuple;
                               1014                 :     SysScanDesc scan;
                               1015                 :     ScanKeyData skey[3];
                               1016                 : 
                               1017                 :     /* Set *constraintOid, to avoid complaints about uninitialized vars */
 1980 dean.a.rasheed           1018 CBC          24 :     *constraintOid = InvalidOid;
 1980 dean.a.rasheed           1019 ECB             : 
 1539 andres                   1020 GIC          24 :     pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
                               1021                 : 
 1980 dean.a.rasheed           1022 CBC          24 :     ScanKeyInit(&skey[0],
                               1023                 :                 Anum_pg_constraint_conrelid,
 1980 dean.a.rasheed           1024 ECB             :                 BTEqualStrategyNumber, F_OIDEQ,
                               1025                 :                 ObjectIdGetDatum(relid));
 1678 tgl                      1026 CBC          24 :     ScanKeyInit(&skey[1],
                               1027                 :                 Anum_pg_constraint_contypid,
                               1028                 :                 BTEqualStrategyNumber, F_OIDEQ,
 1678 tgl                      1029 ECB             :                 ObjectIdGetDatum(InvalidOid));
 1678 tgl                      1030 GIC          24 :     ScanKeyInit(&skey[2],
                               1031                 :                 Anum_pg_constraint_conname,
                               1032                 :                 BTEqualStrategyNumber, F_NAMEEQ,
                               1033                 :                 CStringGetDatum(conname));
 1980 dean.a.rasheed           1034 ECB             : 
 1678 tgl                      1035 CBC          24 :     scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
 1678 tgl                      1036 ECB             :                               NULL, 3, skey);
                               1037                 : 
                               1038                 :     /* There can be at most one matching row */
 1678 tgl                      1039 GIC          24 :     if (HeapTupleIsValid(tuple = systable_getnext(scan)))
                               1040                 :     {
                               1041                 :         Datum       adatum;
                               1042                 :         bool        isNull;
                               1043                 : 
 1601 andres                   1044              24 :         *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
 1980 dean.a.rasheed           1045 ECB             : 
                               1046                 :         /* Extract the conkey array, ie, attnums of constrained columns */
 1980 dean.a.rasheed           1047 GIC          24 :         adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
                               1048                 :                               RelationGetDescr(pg_constraint), &isNull);
 1678 tgl                      1049              24 :         if (!isNull)
                               1050                 :         {
 1678 tgl                      1051 ECB             :             ArrayType  *arr;
                               1052                 :             int         numcols;
                               1053                 :             int16      *attnums;
                               1054                 :             int         i;
                               1055                 : 
 1678 tgl                      1056 GIC          24 :             arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
                               1057              24 :             numcols = ARR_DIMS(arr)[0];
                               1058              24 :             if (ARR_NDIM(arr) != 1 ||
 1678 tgl                      1059 CBC          24 :                 numcols < 0 ||
 1678 tgl                      1060 GIC          24 :                 ARR_HASNULL(arr) ||
                               1061              24 :                 ARR_ELEMTYPE(arr) != INT2OID)
 1678 tgl                      1062 UIC           0 :                 elog(ERROR, "conkey is not a 1-D smallint array");
 1678 tgl                      1063 CBC          24 :             attnums = (int16 *) ARR_DATA_PTR(arr);
                               1064                 : 
                               1065                 :             /* Construct the result value */
 1678 tgl                      1066 GIC          54 :             for (i = 0; i < numcols; i++)
                               1067                 :             {
 1678 tgl                      1068 CBC          30 :                 conattnos = bms_add_member(conattnos,
 1678 tgl                      1069 GIC          30 :                                            attnums[i] - FirstLowInvalidHeapAttributeNumber);
                               1070                 :             }
                               1071                 :         }
 1980 dean.a.rasheed           1072 ECB             :     }
                               1073                 : 
 1980 dean.a.rasheed           1074 GIC          24 :     systable_endscan(scan);
 1980 dean.a.rasheed           1075 ECB             : 
                               1076                 :     /* If no such constraint exists, complain */
 1980 dean.a.rasheed           1077 GIC          24 :     if (!OidIsValid(*constraintOid) && !missing_ok)
 1980 dean.a.rasheed           1078 LBC           0 :         ereport(ERROR,
 1980 dean.a.rasheed           1079 ECB             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                               1080                 :                  errmsg("constraint \"%s\" for table \"%s\" does not exist",
                               1081                 :                         conname, get_rel_name(relid))));
                               1082                 : 
 1539 andres                   1083 GIC          24 :     table_close(pg_constraint, AccessShareLock);
 1980 dean.a.rasheed           1084 ECB             : 
 1980 dean.a.rasheed           1085 GIC          24 :     return conattnos;
 1980 dean.a.rasheed           1086 ECB             : }
                               1087                 : 
                               1088                 : /*
                               1089                 :  * Return the OID of the constraint enforced by the given index in the
                               1090                 :  * given relation; or InvalidOid if no such index is catalogued.
                               1091                 :  *
                               1092                 :  * Much like get_constraint_index, this function is concerned only with the
                               1093                 :  * one constraint that "owns" the given index.  Therefore, constraints of
                               1094                 :  * types other than unique, primary-key, and exclusion are ignored.
                               1095                 :  */
                               1096                 : Oid
 1875 alvherre                 1097 GIC         517 : get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
                               1098                 : {
                               1099                 :     Relation    pg_constraint;
                               1100                 :     SysScanDesc scan;
                               1101                 :     ScanKeyData key;
 1875 alvherre                 1102 ECB             :     HeapTuple   tuple;
 1875 alvherre                 1103 GIC         517 :     Oid         constraintId = InvalidOid;
                               1104                 : 
 1539 andres                   1105 CBC         517 :     pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
                               1106                 : 
 1875 alvherre                 1107 GIC         517 :     ScanKeyInit(&key,
                               1108                 :                 Anum_pg_constraint_conrelid,
                               1109                 :                 BTEqualStrategyNumber,
                               1110                 :                 F_OIDEQ,
                               1111                 :                 ObjectIdGetDatum(relationId));
 1678 tgl                      1112 CBC         517 :     scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
                               1113                 :                               true, NULL, 1, &key);
 1875 alvherre                 1114             619 :     while ((tuple = systable_getnext(scan)) != NULL)
                               1115                 :     {
 1809 tgl                      1116 ECB             :         Form_pg_constraint constrForm;
                               1117                 : 
 1875 alvherre                 1118 GIC         405 :         constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
                               1119                 : 
  184 alvherre                 1120 ECB             :         /* See above */
  184 alvherre                 1121 GIC         405 :         if (constrForm->contype != CONSTRAINT_PRIMARY &&
                               1122             141 :             constrForm->contype != CONSTRAINT_UNIQUE &&
                               1123              99 :             constrForm->contype != CONSTRAINT_EXCLUSION)
  184 alvherre                 1124 CBC          99 :             continue;
                               1125                 : 
 1875 alvherre                 1126 GIC         306 :         if (constrForm->conindid == indexId)
                               1127                 :         {
 1601 andres                   1128             303 :             constraintId = constrForm->oid;
 1875 alvherre                 1129 CBC         303 :             break;
                               1130                 :         }
                               1131                 :     }
 1875 alvherre                 1132 GIC         517 :     systable_endscan(scan);
 1875 alvherre                 1133 ECB             : 
 1539 andres                   1134 GIC         517 :     table_close(pg_constraint, AccessShareLock);
 1875 alvherre                 1135             517 :     return constraintId;
                               1136                 : }
                               1137                 : 
 4023 peter_e                  1138 ECB             : /*
                               1139                 :  * get_domain_constraint_oid
                               1140                 :  *      Find a constraint on the specified domain with the specified name.
                               1141                 :  *      Returns constraint's OID.
                               1142                 :  */
                               1143                 : Oid
 4023 peter_e                  1144 GIC          29 : get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
                               1145                 : {
                               1146                 :     Relation    pg_constraint;
                               1147                 :     HeapTuple   tuple;
                               1148                 :     SysScanDesc scan;
                               1149                 :     ScanKeyData skey[3];
 4023 peter_e                  1150 CBC          29 :     Oid         conOid = InvalidOid;
 4023 peter_e                  1151 ECB             : 
 1539 andres                   1152 CBC          29 :     pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
 4023 peter_e                  1153 ECB             : 
 4023 peter_e                  1154 CBC          29 :     ScanKeyInit(&skey[0],
 1678 tgl                      1155 ECB             :                 Anum_pg_constraint_conrelid,
 1678 tgl                      1156 EUB             :                 BTEqualStrategyNumber, F_OIDEQ,
 1678 tgl                      1157 ECB             :                 ObjectIdGetDatum(InvalidOid));
 1678 tgl                      1158 GIC          29 :     ScanKeyInit(&skey[1],
                               1159                 :                 Anum_pg_constraint_contypid,
 4023 peter_e                  1160 ECB             :                 BTEqualStrategyNumber, F_OIDEQ,
                               1161                 :                 ObjectIdGetDatum(typid));
 1678 tgl                      1162 CBC          29 :     ScanKeyInit(&skey[2],
 1678 tgl                      1163 ECB             :                 Anum_pg_constraint_conname,
                               1164                 :                 BTEqualStrategyNumber, F_NAMEEQ,
                               1165                 :                 CStringGetDatum(conname));
                               1166                 : 
 1678 tgl                      1167 GIC          29 :     scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
 1678 tgl                      1168 ECB             :                               NULL, 3, skey);
                               1169                 : 
                               1170                 :     /* There can be at most one matching row */
 1678 tgl                      1171 CBC          29 :     if (HeapTupleIsValid(tuple = systable_getnext(scan)))
 1601 andres                   1172 GBC          26 :         conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
                               1173                 : 
 4023 peter_e                  1174 GIC          29 :     systable_endscan(scan);
                               1175                 : 
                               1176                 :     /* If no such constraint exists, complain */
 4023 peter_e                  1177 CBC          29 :     if (!OidIsValid(conOid) && !missing_ok)
 4023 peter_e                  1178 GIC           3 :         ereport(ERROR,
 4023 peter_e                  1179 ECB             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                               1180                 :                  errmsg("constraint \"%s\" for domain %s does not exist",
                               1181                 :                         conname, format_type_be(typid))));
                               1182                 : 
 1539 andres                   1183 GIC          26 :     table_close(pg_constraint, AccessShareLock);
                               1184                 : 
 4023 peter_e                  1185              26 :     return conOid;
                               1186                 : }
                               1187                 : 
                               1188                 : /*
                               1189                 :  * get_primary_key_attnos
                               1190                 :  *      Identify the columns in a relation's primary key, if any.
 2614 tgl                      1191 ECB             :  *
                               1192                 :  * Returns a Bitmapset of the column attnos of the primary key's columns,
                               1193                 :  * with attnos being offset by FirstLowInvalidHeapAttributeNumber so that
                               1194                 :  * system columns can be represented.
                               1195                 :  *
                               1196                 :  * If there is no primary key, return NULL.  We also return NULL if the pkey
                               1197                 :  * constraint is deferrable and deferrableOk is false.
                               1198                 :  *
                               1199                 :  * *constraintOid is set to the OID of the pkey constraint, or InvalidOid
                               1200                 :  * on failure.
                               1201                 :  */
                               1202                 : Bitmapset *
 2614 tgl                      1203 GIC         442 : get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
                               1204                 : {
                               1205             442 :     Bitmapset  *pkattnos = NULL;
 2614 tgl                      1206 ECB             :     Relation    pg_constraint;
                               1207                 :     HeapTuple   tuple;
                               1208                 :     SysScanDesc scan;
                               1209                 :     ScanKeyData skey[1];
                               1210                 : 
                               1211                 :     /* Set *constraintOid, to avoid complaints about uninitialized vars */
 2614 tgl                      1212 CBC         442 :     *constraintOid = InvalidOid;
                               1213                 : 
                               1214                 :     /* Scan pg_constraint for constraints of the target rel */
 1539 andres                   1215             442 :     pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
 2614 tgl                      1216 ECB             : 
 2614 tgl                      1217 CBC         442 :     ScanKeyInit(&skey[0],
 2614 tgl                      1218 ECB             :                 Anum_pg_constraint_conrelid,
                               1219                 :                 BTEqualStrategyNumber, F_OIDEQ,
                               1220                 :                 ObjectIdGetDatum(relid));
                               1221                 : 
 1678 tgl                      1222 CBC         442 :     scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
 2614 tgl                      1223 ECB             :                               NULL, 1, skey);
                               1224                 : 
 2614 tgl                      1225 GIC         523 :     while (HeapTupleIsValid(tuple = systable_getnext(scan)))
 2614 tgl                      1226 ECB             :     {
 2614 tgl                      1227 GIC         240 :         Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
 2614 tgl                      1228 ECB             :         Datum       adatum;
                               1229                 :         bool        isNull;
                               1230                 :         ArrayType  *arr;
                               1231                 :         int16      *attnums;
                               1232                 :         int         numkeys;
                               1233                 :         int         i;
                               1234                 : 
                               1235                 :         /* Skip constraints that are not PRIMARY KEYs */
 2614 tgl                      1236 GIC         240 :         if (con->contype != CONSTRAINT_PRIMARY)
                               1237              81 :             continue;
 2614 tgl                      1238 ECB             : 
                               1239                 :         /*
                               1240                 :          * If the primary key is deferrable, but we've been instructed to
                               1241                 :          * ignore deferrable constraints, then we might as well give up
                               1242                 :          * searching, since there can only be a single primary key on a table.
                               1243                 :          */
 2614 tgl                      1244 CBC         159 :         if (con->condeferrable && !deferrableOk)
 2614 tgl                      1245 GIC         159 :             break;
 2614 tgl                      1246 ECB             : 
                               1247                 :         /* Extract the conkey array, ie, attnums of PK's columns */
 2614 tgl                      1248 CBC         156 :         adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
                               1249                 :                               RelationGetDescr(pg_constraint), &isNull);
 2614 tgl                      1250 GIC         156 :         if (isNull)
 2614 tgl                      1251 UIC           0 :             elog(ERROR, "null conkey for constraint %u",
 1601 andres                   1252 ECB             :                  ((Form_pg_constraint) GETSTRUCT(tuple))->oid);
 2118 tgl                      1253 GIC         156 :         arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
 2614                          1254             156 :         numkeys = ARR_DIMS(arr)[0];
                               1255             156 :         if (ARR_NDIM(arr) != 1 ||
 2614 tgl                      1256 CBC         156 :             numkeys < 0 ||
 2614 tgl                      1257 GIC         156 :             ARR_HASNULL(arr) ||
                               1258             156 :             ARR_ELEMTYPE(arr) != INT2OID)
 2614 tgl                      1259 UIC           0 :             elog(ERROR, "conkey is not a 1-D smallint array");
 2614 tgl                      1260 GIC         156 :         attnums = (int16 *) ARR_DATA_PTR(arr);
 2614 tgl                      1261 ECB             : 
                               1262                 :         /* Construct the result value */
 2614 tgl                      1263 GIC         348 :         for (i = 0; i < numkeys; i++)
                               1264                 :         {
 2614 tgl                      1265 CBC         192 :             pkattnos = bms_add_member(pkattnos,
 2118                          1266             192 :                                       attnums[i] - FirstLowInvalidHeapAttributeNumber);
                               1267                 :         }
 1601 andres                   1268             156 :         *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
                               1269                 : 
                               1270                 :         /* No need to search further */
 2614 tgl                      1271             156 :         break;
 2614 tgl                      1272 ECB             :     }
                               1273                 : 
 2614 tgl                      1274 GIC         442 :     systable_endscan(scan);
                               1275                 : 
 1539 andres                   1276             442 :     table_close(pg_constraint, AccessShareLock);
 2614 tgl                      1277 ECB             : 
 2614 tgl                      1278 GIC         442 :     return pkattnos;
 2614 tgl                      1279 ECB             : }
                               1280                 : 
                               1281                 : /*
                               1282                 :  * Extract data from the pg_constraint tuple of a foreign-key constraint.
                               1283                 :  *
                               1284                 :  * All arguments save the first are output arguments.  All output arguments
                               1285                 :  * other than numfks, conkey and confkey can be passed as NULL if caller
                               1286                 :  * doesn't need them.
                               1287                 :  */
                               1288                 : void
 1542 alvherre                 1289 GIC        3481 : DeconstructFkConstraintRow(HeapTuple tuple, int *numfks,
                               1290                 :                            AttrNumber *conkey, AttrNumber *confkey,
                               1291                 :                            Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs,
                               1292                 :                            int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)
                               1293                 : {
                               1294                 :     Datum       adatum;
                               1295                 :     bool        isNull;
 1542 alvherre                 1296 ECB             :     ArrayType  *arr;
                               1297                 :     int         numkeys;
                               1298                 : 
                               1299                 :     /*
                               1300                 :      * We expect the arrays to be 1-D arrays of the right types; verify that.
                               1301                 :      * We don't need to use deconstruct_array() since the array data is just
                               1302                 :      * going to look like a C array of values.
                               1303                 :      */
   15 dgustafsson              1304 GNC        3481 :     adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
                               1305                 :                                     Anum_pg_constraint_conkey);
 1542 alvherre                 1306 CBC        3481 :     arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
 1542 alvherre                 1307 GIC        3481 :     if (ARR_NDIM(arr) != 1 ||
                               1308            3481 :         ARR_HASNULL(arr) ||
                               1309            3481 :         ARR_ELEMTYPE(arr) != INT2OID)
 1542 alvherre                 1310 UIC           0 :         elog(ERROR, "conkey is not a 1-D smallint array");
 1542 alvherre                 1311 CBC        3481 :     numkeys = ARR_DIMS(arr)[0];
 1542 alvherre                 1312 GIC        3481 :     if (numkeys <= 0 || numkeys > INDEX_MAX_KEYS)
 1542 alvherre                 1313 UIC           0 :         elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
 1542 alvherre                 1314 CBC        3481 :     memcpy(conkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
 1542 alvherre                 1315 GIC        3481 :     if ((Pointer) arr != DatumGetPointer(adatum))
 1542 alvherre                 1316 CBC        3481 :         pfree(arr);             /* free de-toasted copy, if any */
                               1317                 : 
   15 dgustafsson              1318 GNC        3481 :     adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
                               1319                 :                                     Anum_pg_constraint_confkey);
 1542 alvherre                 1320 GIC        3481 :     arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
                               1321            3481 :     if (ARR_NDIM(arr) != 1 ||
                               1322            3481 :         ARR_DIMS(arr)[0] != numkeys ||
 1542 alvherre                 1323 CBC        3481 :         ARR_HASNULL(arr) ||
                               1324            3481 :         ARR_ELEMTYPE(arr) != INT2OID)
 1542 alvherre                 1325 UIC           0 :         elog(ERROR, "confkey is not a 1-D smallint array");
 1542 alvherre                 1326 GIC        3481 :     memcpy(confkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
                               1327            3481 :     if ((Pointer) arr != DatumGetPointer(adatum))
                               1328            3481 :         pfree(arr);             /* free de-toasted copy, if any */
                               1329                 : 
                               1330            3481 :     if (pf_eq_oprs)
 1542 alvherre                 1331 ECB             :     {
   15 dgustafsson              1332 GNC        3481 :         adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
                               1333                 :                                         Anum_pg_constraint_conpfeqop);
 1542 alvherre                 1334 GIC        3481 :         arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
 1542 alvherre                 1335 ECB             :         /* see TryReuseForeignKey if you change the test below */
 1542 alvherre                 1336 GBC        3481 :         if (ARR_NDIM(arr) != 1 ||
 1542 alvherre                 1337 GIC        3481 :             ARR_DIMS(arr)[0] != numkeys ||
 1542 alvherre                 1338 CBC        3481 :             ARR_HASNULL(arr) ||
                               1339            3481 :             ARR_ELEMTYPE(arr) != OIDOID)
 1542 alvherre                 1340 LBC           0 :             elog(ERROR, "conpfeqop is not a 1-D Oid array");
 1542 alvherre                 1341 CBC        3481 :         memcpy(pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
                               1342            3481 :         if ((Pointer) arr != DatumGetPointer(adatum))
                               1343            3481 :             pfree(arr);         /* free de-toasted copy, if any */
 1542 alvherre                 1344 EUB             :     }
 1542 alvherre                 1345 ECB             : 
 1542 alvherre                 1346 GIC        3481 :     if (pp_eq_oprs)
                               1347                 :     {
   15 dgustafsson              1348 GNC        2173 :         adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
                               1349                 :                                         Anum_pg_constraint_conppeqop);
 1542 alvherre                 1350 GIC        2173 :         arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
 1542 alvherre                 1351 CBC        2173 :         if (ARR_NDIM(arr) != 1 ||
 1542 alvherre                 1352 GIC        2173 :             ARR_DIMS(arr)[0] != numkeys ||
                               1353            2173 :             ARR_HASNULL(arr) ||
 1542 alvherre                 1354 CBC        2173 :             ARR_ELEMTYPE(arr) != OIDOID)
 1542 alvherre                 1355 UIC           0 :             elog(ERROR, "conppeqop is not a 1-D Oid array");
 1542 alvherre                 1356 GIC        2173 :         memcpy(pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
 1542 alvherre                 1357 CBC        2173 :         if ((Pointer) arr != DatumGetPointer(adatum))
 1542 alvherre                 1358 GIC        2173 :             pfree(arr);         /* free de-toasted copy, if any */
 1542 alvherre                 1359 ECB             :     }
                               1360                 : 
 1542 alvherre                 1361 CBC        3481 :     if (ff_eq_oprs)
                               1362                 :     {
   15 dgustafsson              1363 GNC        2173 :         adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
                               1364                 :                                         Anum_pg_constraint_conffeqop);
 1542 alvherre                 1365 GIC        2173 :         arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
                               1366            2173 :         if (ARR_NDIM(arr) != 1 ||
                               1367            2173 :             ARR_DIMS(arr)[0] != numkeys ||
                               1368            2173 :             ARR_HASNULL(arr) ||
                               1369            2173 :             ARR_ELEMTYPE(arr) != OIDOID)
 1542 alvherre                 1370 LBC           0 :             elog(ERROR, "conffeqop is not a 1-D Oid array");
 1542 alvherre                 1371 GIC        2173 :         memcpy(ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
                               1372            2173 :         if ((Pointer) arr != DatumGetPointer(adatum))
                               1373            2173 :             pfree(arr);         /* free de-toasted copy, if any */
                               1374                 :     }
                               1375                 : 
  487 peter                    1376            3481 :     if (fk_del_set_cols)
                               1377                 :     {
                               1378            2173 :         adatum = SysCacheGetAttr(CONSTROID, tuple,
                               1379                 :                                  Anum_pg_constraint_confdelsetcols, &isNull);
                               1380            2173 :         if (isNull)
                               1381                 :         {
                               1382            2134 :             *num_fk_del_set_cols = 0;
                               1383                 :         }
                               1384                 :         else
  487 peter                    1385 ECB             :         {
                               1386                 :             int         num_delete_cols;
                               1387                 : 
  487 peter                    1388 CBC          39 :             arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
                               1389              39 :             if (ARR_NDIM(arr) != 1 ||
                               1390              39 :                 ARR_HASNULL(arr) ||
  487 peter                    1391 GBC          39 :                 ARR_ELEMTYPE(arr) != INT2OID)
  487 peter                    1392 LBC           0 :                 elog(ERROR, "confdelsetcols is not a 1-D smallint array");
  487 peter                    1393 CBC          39 :             num_delete_cols = ARR_DIMS(arr)[0];
  487 peter                    1394 GBC          39 :             memcpy(fk_del_set_cols, ARR_DATA_PTR(arr), num_delete_cols * sizeof(int16));
  487 peter                    1395 CBC          39 :             if ((Pointer) arr != DatumGetPointer(adatum))
  332 tgl                      1396              39 :                 pfree(arr);     /* free de-toasted copy, if any */
  487 peter                    1397 ECB             : 
  487 peter                    1398 GIC          39 :             *num_fk_del_set_cols = num_delete_cols;
  487 peter                    1399 ECB             :         }
                               1400                 :     }
                               1401                 : 
 1542 alvherre                 1402 CBC        3481 :     *numfks = numkeys;
                               1403            3481 : }
 1542 alvherre                 1404 ECB             : 
 4628 tgl                      1405                 : /*
 4628 tgl                      1406 EUB             :  * Determine whether a relation can be proven functionally dependent on
 2062 peter_e                  1407 ECB             :  * a set of grouping columns.  If so, return true and add the pg_constraint
 4628 tgl                      1408                 :  * OIDs of the constraints needed for the proof to the *constraintDeps list.
                               1409                 :  *
                               1410                 :  * grouping_columns is a list of grouping expressions, in which columns of
                               1411                 :  * the rel of interest are Vars with the indicated varno/varlevelsup.
                               1412                 :  *
                               1413                 :  * Currently we only check to see if the rel has a primary key that is a
                               1414                 :  * subset of the grouping_columns.  We could also use plain unique constraints
                               1415                 :  * if all their columns are known not null, but there's a problem: we need
                               1416                 :  * to be able to represent the not-null-ness as part of the constraints added
 3260 bruce                    1417                 :  * to *constraintDeps.  FIXME whenever not-null constraints get represented
 4628 tgl                      1418                 :  * in pg_constraint.
                               1419                 :  */
                               1420                 : bool
 4628 tgl                      1421 GBC          98 : check_functional_grouping(Oid relid,
 4628 tgl                      1422 ECB             :                           Index varno, Index varlevelsup,
                               1423                 :                           List *grouping_columns,
                               1424                 :                           List **constraintDeps)
                               1425                 : {
                               1426                 :     Bitmapset  *pkattnos;
 2614                          1427                 :     Bitmapset  *groupbyattnos;
                               1428                 :     Oid         constraintOid;
                               1429                 :     ListCell   *gl;
                               1430                 : 
                               1431                 :     /* If the rel has no PK, then we can't prove functional dependency */
 2614 tgl                      1432 CBC          98 :     pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
                               1433              98 :     if (pkattnos == NULL)
                               1434              21 :         return false;
 2614 tgl                      1435 ECB             : 
 2614 tgl                      1436 EUB             :     /* Identify all the rel's columns that appear in grouping_columns */
 2614 tgl                      1437 CBC          77 :     groupbyattnos = NULL;
                               1438             175 :     foreach(gl, grouping_columns)
 4628 tgl                      1439 ECB             :     {
 2614 tgl                      1440 GIC          98 :         Var        *gvar = (Var *) lfirst(gl);
                               1441                 : 
 2614 tgl                      1442 CBC          98 :         if (IsA(gvar, Var) &&
 2614 tgl                      1443 GIC          98 :             gvar->varno == varno &&
 2614 tgl                      1444 CBC          77 :             gvar->varlevelsup == varlevelsup)
 2614 tgl                      1445 GIC          77 :             groupbyattnos = bms_add_member(groupbyattnos,
 2118 tgl                      1446 CBC          77 :                                            gvar->varattno - FirstLowInvalidHeapAttributeNumber);
 4628 tgl                      1447 ECB             :     }
                               1448                 : 
 2614 tgl                      1449 CBC          77 :     if (bms_is_subset(pkattnos, groupbyattnos))
 2614 tgl                      1450 ECB             :     {
 2614 tgl                      1451 EUB             :         /* The PK is a subset of grouping_columns, so we win */
 2614 tgl                      1452 CBC          56 :         *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
                               1453              56 :         return true;
 2614 tgl                      1454 ECB             :     }
                               1455                 : 
 2614 tgl                      1456 GIC          21 :     return false;
 4628 tgl                      1457 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a