LCOV - code coverage report
Current view: top level - src/backend/catalog - heap.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 958 995 96.3 %
Date: 2020-06-05 19:06:29 Functions: 40 40 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * heap.c
       4             :  *    code to create and destroy POSTGRES heap relations
       5             :  *
       6             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/catalog/heap.c
      12             :  *
      13             :  *
      14             :  * INTERFACE ROUTINES
      15             :  *      heap_create()           - Create an uncataloged heap relation
      16             :  *      heap_create_with_catalog() - Create a cataloged relation
      17             :  *      heap_drop_with_catalog() - Removes named relation from catalogs
      18             :  *
      19             :  * NOTES
      20             :  *    this code taken from access/heap/create.c, which contains
      21             :  *    the old heap_create_with_catalog, amcreate, and amdestroy.
      22             :  *    those routines will soon call these routines using the function
      23             :  *    manager,
      24             :  *    just like the poorly named "NewXXX" routines do.  The
      25             :  *    "New" routines are all going to die soon, once and for all!
      26             :  *      -cim 1/13/91
      27             :  *
      28             :  *-------------------------------------------------------------------------
      29             :  */
      30             : #include "postgres.h"
      31             : 
      32             : #include "access/genam.h"
      33             : #include "access/htup_details.h"
      34             : #include "access/multixact.h"
      35             : #include "access/relation.h"
      36             : #include "access/sysattr.h"
      37             : #include "access/table.h"
      38             : #include "access/tableam.h"
      39             : #include "access/transam.h"
      40             : #include "access/xact.h"
      41             : #include "access/xlog.h"
      42             : #include "catalog/binary_upgrade.h"
      43             : #include "catalog/catalog.h"
      44             : #include "catalog/dependency.h"
      45             : #include "catalog/heap.h"
      46             : #include "catalog/index.h"
      47             : #include "catalog/objectaccess.h"
      48             : #include "catalog/partition.h"
      49             : #include "catalog/pg_am.h"
      50             : #include "catalog/pg_attrdef.h"
      51             : #include "catalog/pg_collation.h"
      52             : #include "catalog/pg_constraint.h"
      53             : #include "catalog/pg_foreign_table.h"
      54             : #include "catalog/pg_inherits.h"
      55             : #include "catalog/pg_namespace.h"
      56             : #include "catalog/pg_opclass.h"
      57             : #include "catalog/pg_partitioned_table.h"
      58             : #include "catalog/pg_statistic.h"
      59             : #include "catalog/pg_subscription_rel.h"
      60             : #include "catalog/pg_tablespace.h"
      61             : #include "catalog/pg_type.h"
      62             : #include "catalog/storage.h"
      63             : #include "catalog/storage_xlog.h"
      64             : #include "commands/tablecmds.h"
      65             : #include "commands/typecmds.h"
      66             : #include "executor/executor.h"
      67             : #include "miscadmin.h"
      68             : #include "nodes/nodeFuncs.h"
      69             : #include "optimizer/optimizer.h"
      70             : #include "parser/parse_coerce.h"
      71             : #include "parser/parse_collate.h"
      72             : #include "parser/parse_expr.h"
      73             : #include "parser/parse_relation.h"
      74             : #include "parser/parsetree.h"
      75             : #include "partitioning/partdesc.h"
      76             : #include "storage/lmgr.h"
      77             : #include "storage/predicate.h"
      78             : #include "storage/smgr.h"
      79             : #include "utils/acl.h"
      80             : #include "utils/builtins.h"
      81             : #include "utils/datum.h"
      82             : #include "utils/fmgroids.h"
      83             : #include "utils/inval.h"
      84             : #include "utils/lsyscache.h"
      85             : #include "utils/partcache.h"
      86             : #include "utils/ruleutils.h"
      87             : #include "utils/snapmgr.h"
      88             : #include "utils/syscache.h"
      89             : 
      90             : 
      91             : /* Potentially set by pg_upgrade_support functions */
      92             : Oid         binary_upgrade_next_heap_pg_class_oid = InvalidOid;
      93             : Oid         binary_upgrade_next_toast_pg_class_oid = InvalidOid;
      94             : 
      95             : static void AddNewRelationTuple(Relation pg_class_desc,
      96             :                                 Relation new_rel_desc,
      97             :                                 Oid new_rel_oid,
      98             :                                 Oid new_type_oid,
      99             :                                 Oid reloftype,
     100             :                                 Oid relowner,
     101             :                                 char relkind,
     102             :                                 TransactionId relfrozenxid,
     103             :                                 TransactionId relminmxid,
     104             :                                 Datum relacl,
     105             :                                 Datum reloptions);
     106             : static ObjectAddress AddNewRelationType(const char *typeName,
     107             :                                         Oid typeNamespace,
     108             :                                         Oid new_rel_oid,
     109             :                                         char new_rel_kind,
     110             :                                         Oid ownerid,
     111             :                                         Oid new_row_type,
     112             :                                         Oid new_array_type);
     113             : static void RelationRemoveInheritance(Oid relid);
     114             : static Oid  StoreRelCheck(Relation rel, const char *ccname, Node *expr,
     115             :                           bool is_validated, bool is_local, int inhcount,
     116             :                           bool is_no_inherit, bool is_internal);
     117             : static void StoreConstraints(Relation rel, List *cooked_constraints,
     118             :                              bool is_internal);
     119             : static bool MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
     120             :                                         bool allow_merge, bool is_local,
     121             :                                         bool is_initially_valid,
     122             :                                         bool is_no_inherit);
     123             : static void SetRelationNumChecks(Relation rel, int numchecks);
     124             : static Node *cookConstraint(ParseState *pstate,
     125             :                             Node *raw_constraint,
     126             :                             char *relname);
     127             : 
     128             : 
     129             : /* ----------------------------------------------------------------
     130             :  *              XXX UGLY HARD CODED BADNESS FOLLOWS XXX
     131             :  *
     132             :  *      these should all be moved to someplace in the lib/catalog
     133             :  *      module, if not obliterated first.
     134             :  * ----------------------------------------------------------------
     135             :  */
     136             : 
     137             : 
     138             : /*
     139             :  * Note:
     140             :  *      Should the system special case these attributes in the future?
     141             :  *      Advantage:  consume much less space in the ATTRIBUTE relation.
     142             :  *      Disadvantage:  special cases will be all over the place.
     143             :  */
     144             : 
     145             : /*
     146             :  * The initializers below do not include trailing variable length fields,
     147             :  * but that's OK - we're never going to reference anything beyond the
     148             :  * fixed-size portion of the structure anyway.
     149             :  */
     150             : 
     151             : static const FormData_pg_attribute a1 = {
     152             :     .attname = {"ctid"},
     153             :     .atttypid = TIDOID,
     154             :     .attlen = sizeof(ItemPointerData),
     155             :     .attnum = SelfItemPointerAttributeNumber,
     156             :     .attcacheoff = -1,
     157             :     .atttypmod = -1,
     158             :     .attbyval = false,
     159             :     .attstorage = TYPSTORAGE_PLAIN,
     160             :     .attalign = TYPALIGN_SHORT,
     161             :     .attnotnull = true,
     162             :     .attislocal = true,
     163             : };
     164             : 
     165             : static const FormData_pg_attribute a2 = {
     166             :     .attname = {"xmin"},
     167             :     .atttypid = XIDOID,
     168             :     .attlen = sizeof(TransactionId),
     169             :     .attnum = MinTransactionIdAttributeNumber,
     170             :     .attcacheoff = -1,
     171             :     .atttypmod = -1,
     172             :     .attbyval = true,
     173             :     .attstorage = TYPSTORAGE_PLAIN,
     174             :     .attalign = TYPALIGN_INT,
     175             :     .attnotnull = true,
     176             :     .attislocal = true,
     177             : };
     178             : 
     179             : static const FormData_pg_attribute a3 = {
     180             :     .attname = {"cmin"},
     181             :     .atttypid = CIDOID,
     182             :     .attlen = sizeof(CommandId),
     183             :     .attnum = MinCommandIdAttributeNumber,
     184             :     .attcacheoff = -1,
     185             :     .atttypmod = -1,
     186             :     .attbyval = true,
     187             :     .attstorage = TYPSTORAGE_PLAIN,
     188             :     .attalign = TYPALIGN_INT,
     189             :     .attnotnull = true,
     190             :     .attislocal = true,
     191             : };
     192             : 
     193             : static const FormData_pg_attribute a4 = {
     194             :     .attname = {"xmax"},
     195             :     .atttypid = XIDOID,
     196             :     .attlen = sizeof(TransactionId),
     197             :     .attnum = MaxTransactionIdAttributeNumber,
     198             :     .attcacheoff = -1,
     199             :     .atttypmod = -1,
     200             :     .attbyval = true,
     201             :     .attstorage = TYPSTORAGE_PLAIN,
     202             :     .attalign = TYPALIGN_INT,
     203             :     .attnotnull = true,
     204             :     .attislocal = true,
     205             : };
     206             : 
     207             : static const FormData_pg_attribute a5 = {
     208             :     .attname = {"cmax"},
     209             :     .atttypid = CIDOID,
     210             :     .attlen = sizeof(CommandId),
     211             :     .attnum = MaxCommandIdAttributeNumber,
     212             :     .attcacheoff = -1,
     213             :     .atttypmod = -1,
     214             :     .attbyval = true,
     215             :     .attstorage = TYPSTORAGE_PLAIN,
     216             :     .attalign = TYPALIGN_INT,
     217             :     .attnotnull = true,
     218             :     .attislocal = true,
     219             : };
     220             : 
     221             : /*
     222             :  * We decided to call this attribute "tableoid" rather than say
     223             :  * "classoid" on the basis that in the future there may be more than one
     224             :  * table of a particular class/type. In any case table is still the word
     225             :  * used in SQL.
     226             :  */
     227             : static const FormData_pg_attribute a6 = {
     228             :     .attname = {"tableoid"},
     229             :     .atttypid = OIDOID,
     230             :     .attlen = sizeof(Oid),
     231             :     .attnum = TableOidAttributeNumber,
     232             :     .attcacheoff = -1,
     233             :     .atttypmod = -1,
     234             :     .attbyval = true,
     235             :     .attstorage = TYPSTORAGE_PLAIN,
     236             :     .attalign = TYPALIGN_INT,
     237             :     .attnotnull = true,
     238             :     .attislocal = true,
     239             : };
     240             : 
     241             : static const FormData_pg_attribute *SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};
     242             : 
     243             : /*
     244             :  * This function returns a Form_pg_attribute pointer for a system attribute.
     245             :  * Note that we elog if the presented attno is invalid, which would only
     246             :  * happen if there's a problem upstream.
     247             :  */
     248             : const FormData_pg_attribute *
     249       39440 : SystemAttributeDefinition(AttrNumber attno)
     250             : {
     251       39440 :     if (attno >= 0 || attno < -(int) lengthof(SysAtt))
     252           0 :         elog(ERROR, "invalid system attribute number %d", attno);
     253       39440 :     return SysAtt[-attno - 1];
     254             : }
     255             : 
     256             : /*
     257             :  * If the given name is a system attribute name, return a Form_pg_attribute
     258             :  * pointer for a prototype definition.  If not, return NULL.
     259             :  */
     260             : const FormData_pg_attribute *
     261      387630 : SystemAttributeByName(const char *attname)
     262             : {
     263             :     int         j;
     264             : 
     265     2645702 :     for (j = 0; j < (int) lengthof(SysAtt); j++)
     266             :     {
     267     2297536 :         const FormData_pg_attribute *att = SysAtt[j];
     268             : 
     269     2297536 :         if (strcmp(NameStr(att->attname), attname) == 0)
     270       39464 :             return att;
     271             :     }
     272             : 
     273      348166 :     return NULL;
     274             : }
     275             : 
     276             : 
     277             : /* ----------------------------------------------------------------
     278             :  *              XXX END OF UGLY HARD CODED BADNESS XXX
     279             :  * ---------------------------------------------------------------- */
     280             : 
     281             : 
     282             : /* ----------------------------------------------------------------
     283             :  *      heap_create     - Create an uncataloged heap relation
     284             :  *
     285             :  *      Note API change: the caller must now always provide the OID
     286             :  *      to use for the relation.  The relfilenode may (and, normally,
     287             :  *      should) be left unspecified.
     288             :  *
     289             :  *      rel->rd_rel is initialized by RelationBuildLocalRelation,
     290             :  *      and is mostly zeroes at return.
     291             :  * ----------------------------------------------------------------
     292             :  */
     293             : Relation
     294      185560 : heap_create(const char *relname,
     295             :             Oid relnamespace,
     296             :             Oid reltablespace,
     297             :             Oid relid,
     298             :             Oid relfilenode,
     299             :             Oid accessmtd,
     300             :             TupleDesc tupDesc,
     301             :             char relkind,
     302             :             char relpersistence,
     303             :             bool shared_relation,
     304             :             bool mapped_relation,
     305             :             bool allow_system_table_mods,
     306             :             TransactionId *relfrozenxid,
     307             :             MultiXactId *relminmxid)
     308             : {
     309             :     bool        create_storage;
     310             :     Relation    rel;
     311             : 
     312             :     /* The caller must have provided an OID for the relation. */
     313             :     Assert(OidIsValid(relid));
     314             : 
     315             :     /*
     316             :      * Don't allow creating relations in pg_catalog directly, even though it
     317             :      * is allowed to move user defined relations there. Semantics with search
     318             :      * paths including pg_catalog are too confusing for now.
     319             :      *
     320             :      * But allow creating indexes on relations in pg_catalog even if
     321             :      * allow_system_table_mods = off, upper layers already guarantee it's on a
     322             :      * user defined relation, not a system one.
     323             :      */
     324      259430 :     if (!allow_system_table_mods &&
     325      189272 :         ((IsCatalogNamespace(relnamespace) && relkind != RELKIND_INDEX) ||
     326       73864 :          IsToastNamespace(relnamespace)) &&
     327           6 :         IsNormalProcessingMode())
     328           6 :         ereport(ERROR,
     329             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     330             :                  errmsg("permission denied to create \"%s.%s\"",
     331             :                         get_namespace_name(relnamespace), relname),
     332             :                  errdetail("System catalog modifications are currently disallowed.")));
     333             : 
     334      185554 :     *relfrozenxid = InvalidTransactionId;
     335      185554 :     *relminmxid = InvalidMultiXactId;
     336             : 
     337             :     /* Handle reltablespace for specific relkinds. */
     338      185554 :     switch (relkind)
     339             :     {
     340       47912 :         case RELKIND_VIEW:
     341             :         case RELKIND_COMPOSITE_TYPE:
     342             :         case RELKIND_FOREIGN_TABLE:
     343             : 
     344             :             /*
     345             :              * Force reltablespace to zero if the relation has no physical
     346             :              * storage.  This is mainly just for cleanliness' sake.
     347             :              *
     348             :              * Partitioned tables and indexes don't have physical storage
     349             :              * either, but we want to keep their tablespace settings so that
     350             :              * their children can inherit it.
     351             :              */
     352       47912 :             reltablespace = InvalidOid;
     353       47912 :             break;
     354             : 
     355         962 :         case RELKIND_SEQUENCE:
     356             : 
     357             :             /*
     358             :              * Force reltablespace to zero for sequences, since we don't
     359             :              * support moving them around into different tablespaces.
     360             :              */
     361         962 :             reltablespace = InvalidOid;
     362         962 :             break;
     363      136680 :         default:
     364      136680 :             break;
     365             :     }
     366             : 
     367             :     /*
     368             :      * Decide whether to create storage. If caller passed a valid relfilenode,
     369             :      * storage is already created, so don't do it here.  Also don't create it
     370             :      * for relkinds without physical storage.
     371             :      */
     372      185554 :     if (!RELKIND_HAS_STORAGE(relkind) || OidIsValid(relfilenode))
     373       51208 :         create_storage = false;
     374             :     else
     375             :     {
     376      134346 :         create_storage = true;
     377      134346 :         relfilenode = relid;
     378             :     }
     379             : 
     380             :     /*
     381             :      * Never allow a pg_class entry to explicitly specify the database's
     382             :      * default tablespace in reltablespace; force it to zero instead. This
     383             :      * ensures that if the database is cloned with a different default
     384             :      * tablespace, the pg_class entry will still match where CREATE DATABASE
     385             :      * will put the physically copied relation.
     386             :      *
     387             :      * Yes, this is a bit of a hack.
     388             :      */
     389      185554 :     if (reltablespace == MyDatabaseTableSpace)
     390           4 :         reltablespace = InvalidOid;
     391             : 
     392             :     /*
     393             :      * build the relcache entry.
     394             :      */
     395      185554 :     rel = RelationBuildLocalRelation(relname,
     396             :                                      relnamespace,
     397             :                                      tupDesc,
     398             :                                      relid,
     399             :                                      accessmtd,
     400             :                                      relfilenode,
     401             :                                      reltablespace,
     402             :                                      shared_relation,
     403             :                                      mapped_relation,
     404             :                                      relpersistence,
     405             :                                      relkind);
     406             : 
     407             :     /*
     408             :      * Have the storage manager create the relation's disk file, if needed.
     409             :      *
     410             :      * For relations the callback creates both the main and the init fork, for
     411             :      * indexes only the main fork is created. The other forks will be created
     412             :      * on demand.
     413             :      */
     414      185554 :     if (create_storage)
     415             :     {
     416      134346 :         RelationOpenSmgr(rel);
     417             : 
     418      134346 :         switch (rel->rd_rel->relkind)
     419             :         {
     420           0 :             case RELKIND_VIEW:
     421             :             case RELKIND_COMPOSITE_TYPE:
     422             :             case RELKIND_FOREIGN_TABLE:
     423             :             case RELKIND_PARTITIONED_TABLE:
     424             :             case RELKIND_PARTITIONED_INDEX:
     425             :                 Assert(false);
     426           0 :                 break;
     427             : 
     428       71496 :             case RELKIND_INDEX:
     429             :             case RELKIND_SEQUENCE:
     430       71496 :                 RelationCreateStorage(rel->rd_node, relpersistence);
     431       71496 :                 break;
     432             : 
     433       62850 :             case RELKIND_RELATION:
     434             :             case RELKIND_TOASTVALUE:
     435             :             case RELKIND_MATVIEW:
     436       62850 :                 table_relation_set_new_filenode(rel, &rel->rd_node,
     437             :                                                 relpersistence,
     438             :                                                 relfrozenxid, relminmxid);
     439       62850 :                 break;
     440             :         }
     441       51208 :     }
     442             : 
     443      185554 :     return rel;
     444             : }
     445             : 
     446             : /* ----------------------------------------------------------------
     447             :  *      heap_create_with_catalog        - Create a cataloged relation
     448             :  *
     449             :  *      this is done in multiple steps:
     450             :  *
     451             :  *      1) CheckAttributeNamesTypes() is used to make certain the tuple
     452             :  *         descriptor contains a valid set of attribute names and types
     453             :  *
     454             :  *      2) pg_class is opened and get_relname_relid()
     455             :  *         performs a scan to ensure that no relation with the
     456             :  *         same name already exists.
     457             :  *
     458             :  *      3) heap_create() is called to create the new relation on disk.
     459             :  *
     460             :  *      4) TypeCreate() is called to define a new type corresponding
     461             :  *         to the new relation.
     462             :  *
     463             :  *      5) AddNewRelationTuple() is called to register the
     464             :  *         relation in pg_class.
     465             :  *
     466             :  *      6) AddNewAttributeTuples() is called to register the
     467             :  *         new relation's schema in pg_attribute.
     468             :  *
     469             :  *      7) StoreConstraints is called ()        - vadim 08/22/97
     470             :  *
     471             :  *      8) the relations are closed and the new relation's oid
     472             :  *         is returned.
     473             :  *
     474             :  * ----------------------------------------------------------------
     475             :  */
     476             : 
     477             : /* --------------------------------
     478             :  *      CheckAttributeNamesTypes
     479             :  *
     480             :  *      this is used to make certain the tuple descriptor contains a
     481             :  *      valid set of attribute names and datatypes.  a problem simply
     482             :  *      generates ereport(ERROR) which aborts the current transaction.
     483             :  *
     484             :  *      relkind is the relkind of the relation to be created.
     485             :  *      flags controls which datatypes are allowed, cf CheckAttributeType.
     486             :  * --------------------------------
     487             :  */
     488             : void
     489      113284 : CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
     490             :                          int flags)
     491             : {
     492             :     int         i;
     493             :     int         j;
     494      113284 :     int         natts = tupdesc->natts;
     495             : 
     496             :     /* Sanity check on column count */
     497      113284 :     if (natts < 0 || natts > MaxHeapAttributeNumber)
     498           0 :         ereport(ERROR,
     499             :                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
     500             :                  errmsg("tables can have at most %d columns",
     501             :                         MaxHeapAttributeNumber)));
     502             : 
     503             :     /*
     504             :      * first check for collision with system attribute names
     505             :      *
     506             :      * Skip this for a view or type relation, since those don't have system
     507             :      * attributes.
     508             :      */
     509      113284 :     if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
     510             :     {
     511      349536 :         for (i = 0; i < natts; i++)
     512             :         {
     513      284444 :             Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
     514             : 
     515      284444 :             if (SystemAttributeByName(NameStr(attr->attname)) != NULL)
     516           0 :                 ereport(ERROR,
     517             :                         (errcode(ERRCODE_DUPLICATE_COLUMN),
     518             :                          errmsg("column name \"%s\" conflicts with a system column name",
     519             :                                 NameStr(attr->attname))));
     520             :         }
     521             :     }
     522             : 
     523             :     /*
     524             :      * next check for repeated attribute names
     525             :      */
     526      747056 :     for (i = 1; i < natts; i++)
     527             :     {
     528     9349092 :         for (j = 0; j < i; j++)
     529             :         {
     530     8715320 :             if (strcmp(NameStr(TupleDescAttr(tupdesc, j)->attname),
     531     8715320 :                        NameStr(TupleDescAttr(tupdesc, i)->attname)) == 0)
     532           0 :                 ereport(ERROR,
     533             :                         (errcode(ERRCODE_DUPLICATE_COLUMN),
     534             :                          errmsg("column name \"%s\" specified more than once",
     535             :                                 NameStr(TupleDescAttr(tupdesc, j)->attname))));
     536             :         }
     537             :     }
     538             : 
     539             :     /*
     540             :      * next check the attribute types
     541             :      */
     542      860050 :     for (i = 0; i < natts; i++)
     543             :     {
     544      746776 :         CheckAttributeType(NameStr(TupleDescAttr(tupdesc, i)->attname),
     545             :                            TupleDescAttr(tupdesc, i)->atttypid,
     546             :                            TupleDescAttr(tupdesc, i)->attcollation,
     547             :                            NIL, /* assume we're creating a new rowtype */
     548             :                            flags);
     549             :     }
     550      113274 : }
     551             : 
     552             : /* --------------------------------
     553             :  *      CheckAttributeType
     554             :  *
     555             :  *      Verify that the proposed datatype of an attribute is legal.
     556             :  *      This is needed mainly because there are types (and pseudo-types)
     557             :  *      in the catalogs that we do not support as elements of real tuples.
     558             :  *      We also check some other properties required of a table column.
     559             :  *
     560             :  * If the attribute is being proposed for addition to an existing table or
     561             :  * composite type, pass a one-element list of the rowtype OID as
     562             :  * containing_rowtypes.  When checking a to-be-created rowtype, it's
     563             :  * sufficient to pass NIL, because there could not be any recursive reference
     564             :  * to a not-yet-existing rowtype.
     565             :  *
     566             :  * flags is a bitmask controlling which datatypes we allow.  For the most
     567             :  * part, pseudo-types are disallowed as attribute types, but there are some
     568             :  * exceptions: ANYARRAYOID, RECORDOID, and RECORDARRAYOID can be allowed
     569             :  * in some cases.  (This works because values of those type classes are
     570             :  * self-identifying to some extent.  However, RECORDOID and RECORDARRAYOID
     571             :  * are reliably identifiable only within a session, since the identity info
     572             :  * may use a typmod that is only locally assigned.  The caller is expected
     573             :  * to know whether these cases are safe.)
     574             :  *
     575             :  * flags can also control the phrasing of the error messages.  If
     576             :  * CHKATYPE_IS_PARTKEY is specified, "attname" should be a partition key
     577             :  * column number as text, not a real column name.
     578             :  * --------------------------------
     579             :  */
     580             : void
     581     1008226 : CheckAttributeType(const char *attname,
     582             :                    Oid atttypid, Oid attcollation,
     583             :                    List *containing_rowtypes,
     584             :                    int flags)
     585             : {
     586     1008226 :     char        att_typtype = get_typtype(atttypid);
     587             :     Oid         att_typelem;
     588             : 
     589     1008226 :     if (att_typtype == TYPTYPE_PSEUDO)
     590             :     {
     591             :         /*
     592             :          * We disallow pseudo-type columns, with the exception of ANYARRAY,
     593             :          * RECORD, and RECORD[] when the caller says that those are OK.
     594             :          *
     595             :          * We don't need to worry about recursive containment for RECORD and
     596             :          * RECORD[] because (a) no named composite type should be allowed to
     597             :          * contain those, and (b) two "anonymous" record types couldn't be
     598             :          * considered to be the same type, so infinite recursion isn't
     599             :          * possible.
     600             :          */
     601        2920 :         if (!((atttypid == ANYARRAYOID && (flags & CHKATYPE_ANYARRAY)) ||
     602          16 :               (atttypid == RECORDOID && (flags & CHKATYPE_ANYRECORD)) ||
     603           4 :               (atttypid == RECORDARRAYOID && (flags & CHKATYPE_ANYRECORD))))
     604             :         {
     605          22 :             if (flags & CHKATYPE_IS_PARTKEY)
     606           8 :                 ereport(ERROR,
     607             :                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
     608             :                 /* translator: first %s is an integer not a name */
     609             :                          errmsg("partition key column %s has pseudo-type %s",
     610             :                                 attname, format_type_be(atttypid))));
     611             :             else
     612          14 :                 ereport(ERROR,
     613             :                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
     614             :                          errmsg("column \"%s\" has pseudo-type %s",
     615             :                                 attname, format_type_be(atttypid))));
     616             :         }
     617             :     }
     618     1005314 :     else if (att_typtype == TYPTYPE_DOMAIN)
     619             :     {
     620             :         /*
     621             :          * If it's a domain, recurse to check its base type.
     622             :          */
     623      232712 :         CheckAttributeType(attname, getBaseType(atttypid), attcollation,
     624             :                            containing_rowtypes,
     625             :                            flags);
     626             :     }
     627      772602 :     else if (att_typtype == TYPTYPE_COMPOSITE)
     628             :     {
     629             :         /*
     630             :          * For a composite type, recurse into its attributes.
     631             :          */
     632             :         Relation    relation;
     633             :         TupleDesc   tupdesc;
     634             :         int         i;
     635             : 
     636             :         /*
     637             :          * Check for self-containment.  Eventually we might be able to allow
     638             :          * this (just return without complaint, if so) but it's not clear how
     639             :          * many other places would require anti-recursion defenses before it
     640             :          * would be safe to allow tables to contain their own rowtype.
     641             :          */
     642         366 :         if (list_member_oid(containing_rowtypes, atttypid))
     643          24 :             ereport(ERROR,
     644             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
     645             :                      errmsg("composite type %s cannot be made a member of itself",
     646             :                             format_type_be(atttypid))));
     647             : 
     648         342 :         containing_rowtypes = lappend_oid(containing_rowtypes, atttypid);
     649             : 
     650         342 :         relation = relation_open(get_typ_typrelid(atttypid), AccessShareLock);
     651             : 
     652         342 :         tupdesc = RelationGetDescr(relation);
     653             : 
     654        1112 :         for (i = 0; i < tupdesc->natts; i++)
     655             :         {
     656         778 :             Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
     657             : 
     658         778 :             if (attr->attisdropped)
     659           2 :                 continue;
     660         776 :             CheckAttributeType(NameStr(attr->attname),
     661             :                                attr->atttypid, attr->attcollation,
     662             :                                containing_rowtypes,
     663             :                                flags & ~CHKATYPE_IS_PARTKEY);
     664             :         }
     665             : 
     666         334 :         relation_close(relation, AccessShareLock);
     667             : 
     668         334 :         containing_rowtypes = list_delete_last(containing_rowtypes);
     669             :     }
     670      772236 :     else if (att_typtype == TYPTYPE_RANGE)
     671             :     {
     672             :         /*
     673             :          * If it's a range, recurse to check its subtype.
     674             :          */
     675         110 :         CheckAttributeType(attname, get_range_subtype(atttypid),
     676             :                            get_range_collation(atttypid),
     677             :                            containing_rowtypes,
     678             :                            flags);
     679             :     }
     680      772126 :     else if (OidIsValid((att_typelem = get_element_type(atttypid))))
     681             :     {
     682             :         /*
     683             :          * Must recurse into array types, too, in case they are composite.
     684             :          */
     685       25086 :         CheckAttributeType(attname, att_typelem, attcollation,
     686             :                            containing_rowtypes,
     687             :                            flags);
     688             :     }
     689             : 
     690             :     /*
     691             :      * This might not be strictly invalid per SQL standard, but it is pretty
     692             :      * useless, and it cannot be dumped, so we must disallow it.
     693             :      */
     694     1008156 :     if (!OidIsValid(attcollation) && type_is_collatable(atttypid))
     695             :     {
     696           0 :         if (flags & CHKATYPE_IS_PARTKEY)
     697           0 :             ereport(ERROR,
     698             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
     699             :             /* translator: first %s is an integer not a name */
     700             :                      errmsg("no collation was derived for partition key column %s with collatable type %s",
     701             :                             attname, format_type_be(atttypid)),
     702             :                      errhint("Use the COLLATE clause to set the collation explicitly.")));
     703             :         else
     704           0 :             ereport(ERROR,
     705             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
     706             :                      errmsg("no collation was derived for column \"%s\" with collatable type %s",
     707             :                             attname, format_type_be(atttypid)),
     708             :                      errhint("Use the COLLATE clause to set the collation explicitly.")));
     709             :     }
     710     1008156 : }
     711             : 
     712             : /*
     713             :  * InsertPgAttributeTuple
     714             :  *      Construct and insert a new tuple in pg_attribute.
     715             :  *
     716             :  * Caller has already opened and locked pg_attribute.  new_attribute is the
     717             :  * attribute to insert.  attcacheoff is always initialized to -1, attacl and
     718             :  * attoptions are always initialized to NULL.
     719             :  *
     720             :  * indstate is the index state for CatalogTupleInsertWithInfo.  It can be
     721             :  * passed as NULL, in which case we'll fetch the necessary info.  (Don't do
     722             :  * this when inserting multiple attributes, because it's a tad more
     723             :  * expensive.)
     724             :  */
     725             : void
     726     1258750 : InsertPgAttributeTuple(Relation pg_attribute_rel,
     727             :                        Form_pg_attribute new_attribute,
     728             :                        Datum attoptions,
     729             :                        CatalogIndexState indstate)
     730             : {
     731             :     Datum       values[Natts_pg_attribute];
     732             :     bool        nulls[Natts_pg_attribute];
     733             :     HeapTuple   tup;
     734             : 
     735             :     /* This is a tad tedious, but way cleaner than what we used to do... */
     736     1258750 :     memset(values, 0, sizeof(values));
     737     1258750 :     memset(nulls, false, sizeof(nulls));
     738             : 
     739     1258750 :     values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
     740     1258750 :     values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
     741     1258750 :     values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
     742     1258750 :     values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
     743     1258750 :     values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
     744     1258750 :     values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
     745     1258750 :     values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
     746     1258750 :     values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
     747     1258750 :     values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
     748     1258750 :     values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
     749     1258750 :     values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
     750     1258750 :     values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
     751     1258750 :     values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
     752     1258750 :     values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
     753     1258750 :     values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(new_attribute->atthasmissing);
     754     1258750 :     values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
     755     1258750 :     values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(new_attribute->attgenerated);
     756     1258750 :     values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
     757     1258750 :     values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
     758     1258750 :     values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
     759     1258750 :     values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
     760     1258750 :     values[Anum_pg_attribute_attoptions - 1] = attoptions;
     761             : 
     762             :     /* start out with empty permissions and empty options */
     763     1258750 :     nulls[Anum_pg_attribute_attacl - 1] = true;
     764     1258750 :     nulls[Anum_pg_attribute_attoptions - 1] = attoptions == (Datum) 0;
     765     1258750 :     nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
     766     1258750 :     nulls[Anum_pg_attribute_attmissingval - 1] = true;
     767             : 
     768     1258750 :     tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
     769             : 
     770             :     /* finally insert the new tuple, update the indexes, and clean up */
     771     1258750 :     if (indstate != NULL)
     772     1257244 :         CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
     773             :     else
     774        1506 :         CatalogTupleInsert(pg_attribute_rel, tup);
     775             : 
     776     1258750 :     heap_freetuple(tup);
     777     1258750 : }
     778             : 
     779             : /* --------------------------------
     780             :  *      AddNewAttributeTuples
     781             :  *
     782             :  *      this registers the new relation's schema by adding
     783             :  *      tuples to pg_attribute.
     784             :  * --------------------------------
     785             :  */
     786             : static void
     787      112708 : AddNewAttributeTuples(Oid new_rel_oid,
     788             :                       TupleDesc tupdesc,
     789             :                       char relkind)
     790             : {
     791             :     Form_pg_attribute attr;
     792             :     int         i;
     793             :     Relation    rel;
     794             :     CatalogIndexState indstate;
     795      112708 :     int         natts = tupdesc->natts;
     796             :     ObjectAddress myself,
     797             :                 referenced;
     798             : 
     799             :     /*
     800             :      * open pg_attribute and its indexes.
     801             :      */
     802      112708 :     rel = table_open(AttributeRelationId, RowExclusiveLock);
     803             : 
     804      112708 :     indstate = CatalogOpenIndexes(rel);
     805             : 
     806             :     /*
     807             :      * First we add the user attributes.  This is also a convenient place to
     808             :      * add dependencies on their datatypes and collations.
     809             :      */
     810      857998 :     for (i = 0; i < natts; i++)
     811             :     {
     812      745290 :         attr = TupleDescAttr(tupdesc, i);
     813             :         /* Fill in the correct relation OID */
     814      745290 :         attr->attrelid = new_rel_oid;
     815             :         /* Make sure this is OK, too */
     816      745290 :         attr->attstattarget = -1;
     817             : 
     818      745290 :         InsertPgAttributeTuple(rel, attr, (Datum) 0, indstate);
     819             : 
     820             :         /* Add dependency info */
     821      745290 :         myself.classId = RelationRelationId;
     822      745290 :         myself.objectId = new_rel_oid;
     823      745290 :         myself.objectSubId = i + 1;
     824      745290 :         referenced.classId = TypeRelationId;
     825      745290 :         referenced.objectId = attr->atttypid;
     826      745290 :         referenced.objectSubId = 0;
     827      745290 :         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
     828             : 
     829             :         /* The default collation is pinned, so don't bother recording it */
     830      745290 :         if (OidIsValid(attr->attcollation) &&
     831      319688 :             attr->attcollation != DEFAULT_COLLATION_OID)
     832             :         {
     833      277692 :             referenced.classId = CollationRelationId;
     834      277692 :             referenced.objectId = attr->attcollation;
     835      277692 :             referenced.objectSubId = 0;
     836      277692 :             recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
     837             :         }
     838             :     }
     839             : 
     840             :     /*
     841             :      * Next we add the system attributes.  Skip OID if rel has no OIDs. Skip
     842             :      * all for a view or type relation.  We don't bother with making datatype
     843             :      * dependencies here, since presumably all these types are pinned.
     844             :      */
     845      112708 :     if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
     846             :     {
     847      455462 :         for (i = 0; i < (int) lengthof(SysAtt); i++)
     848             :         {
     849             :             FormData_pg_attribute attStruct;
     850             : 
     851      390396 :             memcpy(&attStruct, SysAtt[i], sizeof(FormData_pg_attribute));
     852             : 
     853             :             /* Fill in the correct relation OID in the copied tuple */
     854      390396 :             attStruct.attrelid = new_rel_oid;
     855             : 
     856      390396 :             InsertPgAttributeTuple(rel, &attStruct, (Datum) 0, indstate);
     857             :         }
     858             :     }
     859             : 
     860             :     /*
     861             :      * clean up
     862             :      */
     863      112708 :     CatalogCloseIndexes(indstate);
     864             : 
     865      112708 :     table_close(rel, RowExclusiveLock);
     866      112708 : }
     867             : 
     868             : /* --------------------------------
     869             :  *      InsertPgClassTuple
     870             :  *
     871             :  *      Construct and insert a new tuple in pg_class.
     872             :  *
     873             :  * Caller has already opened and locked pg_class.
     874             :  * Tuple data is taken from new_rel_desc->rd_rel, except for the
     875             :  * variable-width fields which are not present in a cached reldesc.
     876             :  * relacl and reloptions are passed in Datum form (to avoid having
     877             :  * to reference the data types in heap.h).  Pass (Datum) 0 to set them
     878             :  * to NULL.
     879             :  * --------------------------------
     880             :  */
     881             : void
     882      184122 : InsertPgClassTuple(Relation pg_class_desc,
     883             :                    Relation new_rel_desc,
     884             :                    Oid new_rel_oid,
     885             :                    Datum relacl,
     886             :                    Datum reloptions)
     887             : {
     888      184122 :     Form_pg_class rd_rel = new_rel_desc->rd_rel;
     889             :     Datum       values[Natts_pg_class];
     890             :     bool        nulls[Natts_pg_class];
     891             :     HeapTuple   tup;
     892             : 
     893             :     /* This is a tad tedious, but way cleaner than what we used to do... */
     894      184122 :     memset(values, 0, sizeof(values));
     895      184122 :     memset(nulls, false, sizeof(nulls));
     896             : 
     897      184122 :     values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid);
     898      184122 :     values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
     899      184122 :     values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
     900      184122 :     values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
     901      184122 :     values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
     902      184122 :     values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
     903      184122 :     values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
     904      184122 :     values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
     905      184122 :     values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
     906      184122 :     values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
     907      184122 :     values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
     908      184122 :     values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
     909      184122 :     values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
     910      184122 :     values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
     911      184122 :     values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
     912      184122 :     values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
     913      184122 :     values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
     914      184122 :     values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
     915      184122 :     values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
     916      184122 :     values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
     917      184122 :     values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
     918      184122 :     values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
     919      184122 :     values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
     920      184122 :     values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
     921      184122 :     values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
     922      184122 :     values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
     923      184122 :     values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
     924      184122 :     values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
     925      184122 :     values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
     926      184122 :     values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
     927      184122 :     if (relacl != (Datum) 0)
     928          52 :         values[Anum_pg_class_relacl - 1] = relacl;
     929             :     else
     930      184070 :         nulls[Anum_pg_class_relacl - 1] = true;
     931      184122 :     if (reloptions != (Datum) 0)
     932        1226 :         values[Anum_pg_class_reloptions - 1] = reloptions;
     933             :     else
     934      182896 :         nulls[Anum_pg_class_reloptions - 1] = true;
     935             : 
     936             :     /* relpartbound is set by updating this tuple, if necessary */
     937      184122 :     nulls[Anum_pg_class_relpartbound - 1] = true;
     938             : 
     939      184122 :     tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
     940             : 
     941             :     /* finally insert the new tuple, update the indexes, and clean up */
     942      184122 :     CatalogTupleInsert(pg_class_desc, tup);
     943             : 
     944      184122 :     heap_freetuple(tup);
     945      184122 : }
     946             : 
     947             : /* --------------------------------
     948             :  *      AddNewRelationTuple
     949             :  *
     950             :  *      this registers the new relation in the catalogs by
     951             :  *      adding a tuple to pg_class.
     952             :  * --------------------------------
     953             :  */
     954             : static void
     955      112708 : AddNewRelationTuple(Relation pg_class_desc,
     956             :                     Relation new_rel_desc,
     957             :                     Oid new_rel_oid,
     958             :                     Oid new_type_oid,
     959             :                     Oid reloftype,
     960             :                     Oid relowner,
     961             :                     char relkind,
     962             :                     TransactionId relfrozenxid,
     963             :                     TransactionId relminmxid,
     964             :                     Datum relacl,
     965             :                     Datum reloptions)
     966             : {
     967             :     Form_pg_class new_rel_reltup;
     968             : 
     969             :     /*
     970             :      * first we update some of the information in our uncataloged relation's
     971             :      * relation descriptor.
     972             :      */
     973      112708 :     new_rel_reltup = new_rel_desc->rd_rel;
     974             : 
     975      112708 :     switch (relkind)
     976             :     {
     977       61418 :         case RELKIND_RELATION:
     978             :         case RELKIND_MATVIEW:
     979             :         case RELKIND_INDEX:
     980             :         case RELKIND_TOASTVALUE:
     981             :             /* The relation is real, but as yet empty */
     982       61418 :             new_rel_reltup->relpages = 0;
     983       61418 :             new_rel_reltup->reltuples = 0;
     984       61418 :             new_rel_reltup->relallvisible = 0;
     985       61418 :             break;
     986         962 :         case RELKIND_SEQUENCE:
     987             :             /* Sequences always have a known size */
     988         962 :             new_rel_reltup->relpages = 1;
     989         962 :             new_rel_reltup->reltuples = 1;
     990         962 :             new_rel_reltup->relallvisible = 0;
     991         962 :             break;
     992       50328 :         default:
     993             :             /* Views, etc, have no disk storage */
     994       50328 :             new_rel_reltup->relpages = 0;
     995       50328 :             new_rel_reltup->reltuples = 0;
     996       50328 :             new_rel_reltup->relallvisible = 0;
     997       50328 :             break;
     998             :     }
     999             : 
    1000      112708 :     new_rel_reltup->relfrozenxid = relfrozenxid;
    1001      112708 :     new_rel_reltup->relminmxid = relminmxid;
    1002      112708 :     new_rel_reltup->relowner = relowner;
    1003      112708 :     new_rel_reltup->reltype = new_type_oid;
    1004      112708 :     new_rel_reltup->reloftype = reloftype;
    1005             : 
    1006             :     /* relispartition is always set by updating this tuple later */
    1007      112708 :     new_rel_reltup->relispartition = false;
    1008             : 
    1009      112708 :     new_rel_desc->rd_att->tdtypeid = new_type_oid;
    1010             : 
    1011             :     /* Now build and insert the tuple */
    1012      112708 :     InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
    1013             :                        relacl, reloptions);
    1014      112708 : }
    1015             : 
    1016             : 
    1017             : /* --------------------------------
    1018             :  *      AddNewRelationType -
    1019             :  *
    1020             :  *      define a composite type corresponding to the new relation
    1021             :  * --------------------------------
    1022             :  */
    1023             : static ObjectAddress
    1024      112708 : AddNewRelationType(const char *typeName,
    1025             :                    Oid typeNamespace,
    1026             :                    Oid new_rel_oid,
    1027             :                    char new_rel_kind,
    1028             :                    Oid ownerid,
    1029             :                    Oid new_row_type,
    1030             :                    Oid new_array_type)
    1031             : {
    1032             :     return
    1033      112708 :         TypeCreate(new_row_type,    /* optional predetermined OID */
    1034             :                    typeName,    /* type name */
    1035             :                    typeNamespace,   /* type namespace */
    1036             :                    new_rel_oid, /* relation oid */
    1037             :                    new_rel_kind,    /* relation kind */
    1038             :                    ownerid,     /* owner's ID */
    1039             :                    -1,          /* internal size (varlena) */
    1040             :                    TYPTYPE_COMPOSITE,   /* type-type (composite) */
    1041             :                    TYPCATEGORY_COMPOSITE,   /* type-category (ditto) */
    1042             :                    false,       /* composite types are never preferred */
    1043             :                    DEFAULT_TYPDELIM,    /* default array delimiter */
    1044             :                    F_RECORD_IN, /* input procedure */
    1045             :                    F_RECORD_OUT,    /* output procedure */
    1046             :                    F_RECORD_RECV,   /* receive procedure */
    1047             :                    F_RECORD_SEND,   /* send procedure */
    1048             :                    InvalidOid,  /* typmodin procedure - none */
    1049             :                    InvalidOid,  /* typmodout procedure - none */
    1050             :                    InvalidOid,  /* analyze procedure - default */
    1051             :                    InvalidOid,  /* array element type - irrelevant */
    1052             :                    false,       /* this is not an array type */
    1053             :                    new_array_type,  /* array type if any */
    1054             :                    InvalidOid,  /* domain base type - irrelevant */
    1055             :                    NULL,        /* default value - none */
    1056             :                    NULL,        /* default binary representation */
    1057             :                    false,       /* passed by reference */
    1058             :                    TYPALIGN_DOUBLE, /* alignment - must be the largest! */
    1059             :                    TYPSTORAGE_EXTENDED, /* fully TOASTable */
    1060             :                    -1,          /* typmod */
    1061             :                    0,           /* array dimensions for typBaseType */
    1062             :                    false,       /* Type NOT NULL */
    1063             :                    InvalidOid); /* rowtypes never have a collation */
    1064             : }
    1065             : 
    1066             : /* --------------------------------
    1067             :  *      heap_create_with_catalog
    1068             :  *
    1069             :  *      creates a new cataloged relation.  see comments above.
    1070             :  *
    1071             :  * Arguments:
    1072             :  *  relname: name to give to new rel
    1073             :  *  relnamespace: OID of namespace it goes in
    1074             :  *  reltablespace: OID of tablespace it goes in
    1075             :  *  relid: OID to assign to new rel, or InvalidOid to select a new OID
    1076             :  *  reltypeid: OID to assign to rel's rowtype, or InvalidOid to select one
    1077             :  *  reloftypeid: if a typed table, OID of underlying type; else InvalidOid
    1078             :  *  ownerid: OID of new rel's owner
    1079             :  *  tupdesc: tuple descriptor (source of column definitions)
    1080             :  *  cooked_constraints: list of precooked check constraints and defaults
    1081             :  *  relkind: relkind for new rel
    1082             :  *  relpersistence: rel's persistence status (permanent, temp, or unlogged)
    1083             :  *  shared_relation: true if it's to be a shared relation
    1084             :  *  mapped_relation: true if the relation will use the relfilenode map
    1085             :  *  oncommit: ON COMMIT marking (only relevant if it's a temp table)
    1086             :  *  reloptions: reloptions in Datum form, or (Datum) 0 if none
    1087             :  *  use_user_acl: true if should look for user-defined default permissions;
    1088             :  *      if false, relacl is always set NULL
    1089             :  *  allow_system_table_mods: true to allow creation in system namespaces
    1090             :  *  is_internal: is this a system-generated catalog?
    1091             :  *
    1092             :  * Output parameters:
    1093             :  *  typaddress: if not null, gets the object address of the new pg_type entry
    1094             :  *
    1095             :  * Returns the OID of the new relation
    1096             :  * --------------------------------
    1097             :  */
    1098             : Oid
    1099      112738 : heap_create_with_catalog(const char *relname,
    1100             :                          Oid relnamespace,
    1101             :                          Oid reltablespace,
    1102             :                          Oid relid,
    1103             :                          Oid reltypeid,
    1104             :                          Oid reloftypeid,
    1105             :                          Oid ownerid,
    1106             :                          Oid accessmtd,
    1107             :                          TupleDesc tupdesc,
    1108             :                          List *cooked_constraints,
    1109             :                          char relkind,
    1110             :                          char relpersistence,
    1111             :                          bool shared_relation,
    1112             :                          bool mapped_relation,
    1113             :                          OnCommitAction oncommit,
    1114             :                          Datum reloptions,
    1115             :                          bool use_user_acl,
    1116             :                          bool allow_system_table_mods,
    1117             :                          bool is_internal,
    1118             :                          Oid relrewrite,
    1119             :                          ObjectAddress *typaddress)
    1120             : {
    1121             :     Relation    pg_class_desc;
    1122             :     Relation    new_rel_desc;
    1123             :     Acl        *relacl;
    1124             :     Oid         existing_relid;
    1125             :     Oid         old_type_oid;
    1126             :     Oid         new_type_oid;
    1127             :     ObjectAddress new_type_addr;
    1128      112738 :     Oid         new_array_oid = InvalidOid;
    1129             :     TransactionId relfrozenxid;
    1130             :     MultiXactId relminmxid;
    1131             : 
    1132      112738 :     pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
    1133             : 
    1134             :     /*
    1135             :      * sanity checks
    1136             :      */
    1137             :     Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
    1138             : 
    1139             :     /*
    1140             :      * Validate proposed tupdesc for the desired relkind.  If
    1141             :      * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
    1142             :      * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
    1143             :      */
    1144      112738 :     CheckAttributeNamesTypes(tupdesc, relkind,
    1145             :                              allow_system_table_mods ? CHKATYPE_ANYARRAY : 0);
    1146             : 
    1147             :     /*
    1148             :      * This would fail later on anyway, if the relation already exists.  But
    1149             :      * by catching it here we can emit a nicer error message.
    1150             :      */
    1151      112728 :     existing_relid = get_relname_relid(relname, relnamespace);
    1152      112728 :     if (existing_relid != InvalidOid)
    1153          14 :         ereport(ERROR,
    1154             :                 (errcode(ERRCODE_DUPLICATE_TABLE),
    1155             :                  errmsg("relation \"%s\" already exists", relname)));
    1156             : 
    1157             :     /*
    1158             :      * Since we are going to create a rowtype as well, also check for
    1159             :      * collision with an existing type name.  If there is one and it's an
    1160             :      * autogenerated array, we can rename it out of the way; otherwise we can
    1161             :      * at least give a good error message.
    1162             :      */
    1163      112714 :     old_type_oid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
    1164             :                                    CStringGetDatum(relname),
    1165             :                                    ObjectIdGetDatum(relnamespace));
    1166      112714 :     if (OidIsValid(old_type_oid))
    1167             :     {
    1168           2 :         if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
    1169           0 :             ereport(ERROR,
    1170             :                     (errcode(ERRCODE_DUPLICATE_OBJECT),
    1171             :                      errmsg("type \"%s\" already exists", relname),
    1172             :                      errhint("A relation has an associated type of the same name, "
    1173             :                              "so you must use a name that doesn't conflict "
    1174             :                              "with any existing type.")));
    1175             :     }
    1176             : 
    1177             :     /*
    1178             :      * Shared relations must be in pg_global (last-ditch check)
    1179             :      */
    1180      112714 :     if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
    1181           0 :         elog(ERROR, "shared relations must be placed in pg_global tablespace");
    1182             : 
    1183             :     /*
    1184             :      * Allocate an OID for the relation, unless we were told what to use.
    1185             :      *
    1186             :      * The OID will be the relfilenode as well, so make sure it doesn't
    1187             :      * collide with either pg_class OIDs or existing physical files.
    1188             :      */
    1189      112714 :     if (!OidIsValid(relid))
    1190             :     {
    1191             :         /* Use binary-upgrade override for pg_class.oid/relfilenode? */
    1192       79778 :         if (IsBinaryUpgrade &&
    1193         802 :             (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
    1194         632 :              relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
    1195         586 :              relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
    1196             :              relkind == RELKIND_PARTITIONED_TABLE))
    1197             :         {
    1198        1324 :             if (!OidIsValid(binary_upgrade_next_heap_pg_class_oid))
    1199           0 :                 ereport(ERROR,
    1200             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1201             :                          errmsg("pg_class heap OID value not set when in binary upgrade mode")));
    1202             : 
    1203        1324 :             relid = binary_upgrade_next_heap_pg_class_oid;
    1204        1324 :             binary_upgrade_next_heap_pg_class_oid = InvalidOid;
    1205             :         }
    1206             :         /* There might be no TOAST table, so we have to test for it. */
    1207       78454 :         else if (IsBinaryUpgrade &&
    1208         444 :                  OidIsValid(binary_upgrade_next_toast_pg_class_oid) &&
    1209             :                  relkind == RELKIND_TOASTVALUE)
    1210             :         {
    1211         444 :             relid = binary_upgrade_next_toast_pg_class_oid;
    1212         444 :             binary_upgrade_next_toast_pg_class_oid = InvalidOid;
    1213             :         }
    1214             :         else
    1215       78010 :             relid = GetNewRelFileNode(reltablespace, pg_class_desc,
    1216             :                                       relpersistence);
    1217             :     }
    1218             : 
    1219             :     /*
    1220             :      * Determine the relation's initial permissions.
    1221             :      */
    1222      112714 :     if (use_user_acl)
    1223             :     {
    1224       70482 :         switch (relkind)
    1225             :         {
    1226       69110 :             case RELKIND_RELATION:
    1227             :             case RELKIND_VIEW:
    1228             :             case RELKIND_MATVIEW:
    1229             :             case RELKIND_FOREIGN_TABLE:
    1230             :             case RELKIND_PARTITIONED_TABLE:
    1231       69110 :                 relacl = get_user_default_acl(OBJECT_TABLE, ownerid,
    1232             :                                               relnamespace);
    1233       69110 :                 break;
    1234         962 :             case RELKIND_SEQUENCE:
    1235         962 :                 relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
    1236             :                                               relnamespace);
    1237         962 :                 break;
    1238         410 :             default:
    1239         410 :                 relacl = NULL;
    1240         410 :                 break;
    1241             :         }
    1242             :     }
    1243             :     else
    1244       42232 :         relacl = NULL;
    1245             : 
    1246             :     /*
    1247             :      * Create the relcache entry (mostly dummy at this point) and the physical
    1248             :      * disk file.  (If we fail further down, it's the smgr's responsibility to
    1249             :      * remove the disk file again.)
    1250             :      */
    1251      112714 :     new_rel_desc = heap_create(relname,
    1252             :                                relnamespace,
    1253             :                                reltablespace,
    1254             :                                relid,
    1255             :                                InvalidOid,
    1256             :                                accessmtd,
    1257             :                                tupdesc,
    1258             :                                relkind,
    1259             :                                relpersistence,
    1260             :                                shared_relation,
    1261             :                                mapped_relation,
    1262             :                                allow_system_table_mods,
    1263             :                                &relfrozenxid,
    1264             :                                &relminmxid);
    1265             : 
    1266             :     Assert(relid == RelationGetRelid(new_rel_desc));
    1267             : 
    1268      112708 :     new_rel_desc->rd_rel->relrewrite = relrewrite;
    1269             : 
    1270             :     /*
    1271             :      * Decide whether to create an array type over the relation's rowtype. We
    1272             :      * do not create any array types for system catalogs (ie, those made
    1273             :      * during initdb). We do not create them where the use of a relation as
    1274             :      * such is an implementation detail: toast tables, sequences and indexes.
    1275             :      */
    1276      112708 :     if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
    1277       11250 :                               relkind == RELKIND_VIEW ||
    1278       11076 :                               relkind == RELKIND_MATVIEW ||
    1279       10806 :                               relkind == RELKIND_FOREIGN_TABLE ||
    1280       10396 :                               relkind == RELKIND_COMPOSITE_TYPE ||
    1281             :                               relkind == RELKIND_PARTITIONED_TABLE))
    1282       23104 :         new_array_oid = AssignTypeArrayOid();
    1283             : 
    1284             :     /*
    1285             :      * Since defining a relation also defines a complex type, we add a new
    1286             :      * system type corresponding to the new relation.  The OID of the type can
    1287             :      * be preselected by the caller, but if reltypeid is InvalidOid, we'll
    1288             :      * generate a new OID for it.
    1289             :      *
    1290             :      * NOTE: we could get a unique-index failure here, in case someone else is
    1291             :      * creating the same type name in parallel but hadn't committed yet when
    1292             :      * we checked for a duplicate name above.
    1293             :      */
    1294      112708 :     new_type_addr = AddNewRelationType(relname,
    1295             :                                        relnamespace,
    1296             :                                        relid,
    1297             :                                        relkind,
    1298             :                                        ownerid,
    1299             :                                        reltypeid,
    1300             :                                        new_array_oid);
    1301      112708 :     new_type_oid = new_type_addr.objectId;
    1302      112708 :     if (typaddress)
    1303         410 :         *typaddress = new_type_addr;
    1304             : 
    1305             :     /*
    1306             :      * Now make the array type if wanted.
    1307             :      */
    1308      112708 :     if (OidIsValid(new_array_oid))
    1309             :     {
    1310             :         char       *relarrayname;
    1311             : 
    1312       23104 :         relarrayname = makeArrayTypeName(relname, relnamespace);
    1313             : 
    1314       23104 :         TypeCreate(new_array_oid,   /* force the type's OID to this */
    1315             :                    relarrayname,    /* Array type name */
    1316             :                    relnamespace,    /* Same namespace as parent */
    1317             :                    InvalidOid,  /* Not composite, no relationOid */
    1318             :                    0,           /* relkind, also N/A here */
    1319             :                    ownerid,     /* owner's ID */
    1320             :                    -1,          /* Internal size (varlena) */
    1321             :                    TYPTYPE_BASE,    /* Not composite - typelem is */
    1322             :                    TYPCATEGORY_ARRAY,   /* type-category (array) */
    1323             :                    false,       /* array types are never preferred */
    1324             :                    DEFAULT_TYPDELIM,    /* default array delimiter */
    1325             :                    F_ARRAY_IN,  /* array input proc */
    1326             :                    F_ARRAY_OUT, /* array output proc */
    1327             :                    F_ARRAY_RECV,    /* array recv (bin) proc */
    1328             :                    F_ARRAY_SEND,    /* array send (bin) proc */
    1329             :                    InvalidOid,  /* typmodin procedure - none */
    1330             :                    InvalidOid,  /* typmodout procedure - none */
    1331             :                    F_ARRAY_TYPANALYZE,  /* array analyze procedure */
    1332             :                    new_type_oid,    /* array element type - the rowtype */
    1333             :                    true,        /* yes, this is an array type */
    1334             :                    InvalidOid,  /* this has no array type */
    1335             :                    InvalidOid,  /* domain base type - irrelevant */
    1336             :                    NULL,        /* default value - none */
    1337             :                    NULL,        /* default binary representation */
    1338             :                    false,       /* passed by reference */
    1339             :                    TYPALIGN_DOUBLE, /* alignment - must be the largest! */
    1340             :                    TYPSTORAGE_EXTENDED, /* fully TOASTable */
    1341             :                    -1,          /* typmod */
    1342             :                    0,           /* array dimensions for typBaseType */
    1343             :                    false,       /* Type NOT NULL */
    1344             :                    InvalidOid); /* rowtypes never have a collation */
    1345             : 
    1346       23104 :         pfree(relarrayname);
    1347             :     }
    1348             : 
    1349             :     /*
    1350             :      * now create an entry in pg_class for the relation.
    1351             :      *
    1352             :      * NOTE: we could get a unique-index failure here, in case someone else is
    1353             :      * creating the same relation name in parallel but hadn't committed yet
    1354             :      * when we checked for a duplicate name above.
    1355             :      */
    1356      112708 :     AddNewRelationTuple(pg_class_desc,
    1357             :                         new_rel_desc,
    1358             :                         relid,
    1359             :                         new_type_oid,
    1360             :                         reloftypeid,
    1361             :                         ownerid,
    1362             :                         relkind,
    1363             :                         relfrozenxid,
    1364             :                         relminmxid,
    1365             :                         PointerGetDatum(relacl),
    1366             :                         reloptions);
    1367             : 
    1368             :     /*
    1369             :      * now add tuples to pg_attribute for the attributes in our new relation.
    1370             :      */
    1371      112708 :     AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
    1372             : 
    1373             :     /*
    1374             :      * Make a dependency link to force the relation to be deleted if its
    1375             :      * namespace is.  Also make a dependency link to its owner, as well as
    1376             :      * dependencies for any roles mentioned in the default ACL.
    1377             :      *
    1378             :      * For composite types, these dependencies are tracked for the pg_type
    1379             :      * entry, so we needn't record them here.  Likewise, TOAST tables don't
    1380             :      * need a namespace dependency (they live in a pinned namespace) nor an
    1381             :      * owner dependency (they depend indirectly through the parent table), nor
    1382             :      * should they have any ACL entries.  The same applies for extension
    1383             :      * dependencies.
    1384             :      *
    1385             :      * Also, skip this in bootstrap mode, since we don't make dependencies
    1386             :      * while bootstrapping.
    1387             :      */
    1388      112708 :     if (relkind != RELKIND_COMPOSITE_TYPE &&
    1389       91676 :         relkind != RELKIND_TOASTVALUE &&
    1390       91676 :         !IsBootstrapProcessingMode())
    1391             :     {
    1392             :         ObjectAddress myself,
    1393             :                     referenced;
    1394             : 
    1395       70912 :         myself.classId = RelationRelationId;
    1396       70912 :         myself.objectId = relid;
    1397       70912 :         myself.objectSubId = 0;
    1398             : 
    1399       70912 :         referenced.classId = NamespaceRelationId;
    1400       70912 :         referenced.objectId = relnamespace;
    1401       70912 :         referenced.objectSubId = 0;
    1402       70912 :         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
    1403             : 
    1404       70912 :         recordDependencyOnOwner(RelationRelationId, relid, ownerid);
    1405             : 
    1406       70912 :         recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
    1407             : 
    1408       70912 :         recordDependencyOnCurrentExtension(&myself, false);
    1409             : 
    1410       70912 :         if (reloftypeid)
    1411             :         {
    1412          46 :             referenced.classId = TypeRelationId;
    1413          46 :             referenced.objectId = reloftypeid;
    1414          46 :             referenced.objectSubId = 0;
    1415          46 :             recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
    1416             :         }
    1417             : 
    1418             :         /*
    1419             :          * Make a dependency link to force the relation to be deleted if its
    1420             :          * access method is. Do this only for relation and materialized views.
    1421             :          *
    1422             :          * No need to add an explicit dependency for the toast table, as the
    1423             :          * main table depends on it.
    1424             :          */
    1425       70912 :         if (relkind == RELKIND_RELATION ||
    1426             :             relkind == RELKIND_MATVIEW)
    1427             :         {
    1428       20032 :             referenced.classId = AccessMethodRelationId;
    1429       20032 :             referenced.objectId = accessmtd;
    1430       20032 :             referenced.objectSubId = 0;
    1431       20032 :             recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
    1432             :         }
    1433             :     }
    1434             : 
    1435             :     /* Post creation hook for new relation */
    1436      112708 :     InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
    1437             : 
    1438             :     /*
    1439             :      * Store any supplied constraints and defaults.
    1440             :      *
    1441             :      * NB: this may do a CommandCounterIncrement and rebuild the relcache
    1442             :      * entry, so the relation must be valid and self-consistent at this point.
    1443             :      * In particular, there are not yet constraints and defaults anywhere.
    1444             :      */
    1445      112708 :     StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
    1446             : 
    1447             :     /*
    1448             :      * If there's a special on-commit action, remember it
    1449             :      */
    1450      112708 :     if (oncommit != ONCOMMIT_NOOP)
    1451         108 :         register_on_commit_action(relid, oncommit);
    1452             : 
    1453             :     /*
    1454             :      * ok, the relation has been cataloged, so close our relations and return
    1455             :      * the OID of the newly created relation.
    1456             :      */
    1457      112708 :     table_close(new_rel_desc, NoLock);  /* do not unlock till end of xact */
    1458      112708 :     table_close(pg_class_desc, RowExclusiveLock);
    1459             : 
    1460      112708 :     return relid;
    1461             : }
    1462             : 
    1463             : /*
    1464             :  *      RelationRemoveInheritance
    1465             :  *
    1466             :  * Formerly, this routine checked for child relations and aborted the
    1467             :  * deletion if any were found.  Now we rely on the dependency mechanism
    1468             :  * to check for or delete child relations.  By the time we get here,
    1469             :  * there are no children and we need only remove any pg_inherits rows
    1470             :  * linking this relation to its parent(s).
    1471             :  */
    1472             : static void
    1473       23024 : RelationRemoveInheritance(Oid relid)
    1474             : {
    1475             :     Relation    catalogRelation;
    1476             :     SysScanDesc scan;
    1477             :     ScanKeyData key;
    1478             :     HeapTuple   tuple;
    1479             : 
    1480       23024 :     catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
    1481             : 
    1482       23024 :     ScanKeyInit(&key,
    1483             :                 Anum_pg_inherits_inhrelid,
    1484             :                 BTEqualStrategyNumber, F_OIDEQ,
    1485             :                 ObjectIdGetDatum(relid));
    1486             : 
    1487       23024 :     scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
    1488             :                               NULL, 1, &key);
    1489             : 
    1490       27332 :     while (HeapTupleIsValid(tuple = systable_getnext(scan)))
    1491        4308 :         CatalogTupleDelete(catalogRelation, &tuple->t_self);
    1492             : 
    1493       23024 :     systable_endscan(scan);
    1494       23024 :     table_close(catalogRelation, RowExclusiveLock);
    1495       23024 : }
    1496             : 
    1497             : /*
    1498             :  *      DeleteRelationTuple
    1499             :  *
    1500             :  * Remove pg_class row for the given relid.
    1501             :  *
    1502             :  * Note: this is shared by relation deletion and index deletion.  It's
    1503             :  * not intended for use anyplace else.
    1504             :  */
    1505             : void
    1506       35428 : DeleteRelationTuple(Oid relid)
    1507             : {
    1508             :     Relation    pg_class_desc;
    1509             :     HeapTuple   tup;
    1510             : 
    1511             :     /* Grab an appropriate lock on the pg_class relation */
    1512       35428 :     pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
    1513             : 
    1514       35428 :     tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1515       35428 :     if (!HeapTupleIsValid(tup))
    1516           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
    1517             : 
    1518             :     /* delete the relation tuple from pg_class, and finish up */
    1519       35428 :     CatalogTupleDelete(pg_class_desc, &tup->t_self);
    1520             : 
    1521       35428 :     ReleaseSysCache(tup);
    1522             : 
    1523       35428 :     table_close(pg_class_desc, RowExclusiveLock);
    1524       35428 : }
    1525             : 
    1526             : /*
    1527             :  *      DeleteAttributeTuples
    1528             :  *
    1529             :  * Remove pg_attribute rows for the given relid.
    1530             :  *
    1531             :  * Note: this is shared by relation deletion and index deletion.  It's
    1532             :  * not intended for use anyplace else.
    1533             :  */
    1534             : void
    1535       35428 : DeleteAttributeTuples(Oid relid)
    1536             : {
    1537             :     Relation    attrel;
    1538             :     SysScanDesc scan;
    1539             :     ScanKeyData key[1];
    1540             :     HeapTuple   atttup;
    1541             : 
    1542             :     /* Grab an appropriate lock on the pg_attribute relation */
    1543       35428 :     attrel = table_open(AttributeRelationId, RowExclusiveLock);
    1544             : 
    1545             :     /* Use the index to scan only attributes of the target relation */
    1546       35428 :     ScanKeyInit(&key[0],
    1547             :                 Anum_pg_attribute_attrelid,
    1548             :                 BTEqualStrategyNumber, F_OIDEQ,
    1549             :                 ObjectIdGetDatum(relid));
    1550             : 
    1551       35428 :     scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
    1552             :                               NULL, 1, key);
    1553             : 
    1554             :     /* Delete all the matching tuples */
    1555      240358 :     while ((atttup = systable_getnext(scan)) != NULL)
    1556      204930 :         CatalogTupleDelete(attrel, &atttup->t_self);
    1557             : 
    1558             :     /* Clean up after the scan */
    1559       35428 :     systable_endscan(scan);
    1560       35428 :     table_close(attrel, RowExclusiveLock);
    1561       35428 : }
    1562             : 
    1563             : /*
    1564             :  *      DeleteSystemAttributeTuples
    1565             :  *
    1566             :  * Remove pg_attribute rows for system columns of the given relid.
    1567             :  *
    1568             :  * Note: this is only used when converting a table to a view.  Views don't
    1569             :  * have system columns, so we should remove them from pg_attribute.
    1570             :  */
    1571             : void
    1572          10 : DeleteSystemAttributeTuples(Oid relid)
    1573             : {
    1574             :     Relation    attrel;
    1575             :     SysScanDesc scan;
    1576             :     ScanKeyData key[2];
    1577             :     HeapTuple   atttup;
    1578             : 
    1579             :     /* Grab an appropriate lock on the pg_attribute relation */
    1580          10 :     attrel = table_open(AttributeRelationId, RowExclusiveLock);
    1581             : 
    1582             :     /* Use the index to scan only system attributes of the target relation */
    1583          10 :     ScanKeyInit(&key[0],
    1584             :                 Anum_pg_attribute_attrelid,
    1585             :                 BTEqualStrategyNumber, F_OIDEQ,
    1586             :                 ObjectIdGetDatum(relid));
    1587          10 :     ScanKeyInit(&key[1],
    1588             :                 Anum_pg_attribute_attnum,
    1589             :                 BTLessEqualStrategyNumber, F_INT2LE,
    1590             :                 Int16GetDatum(0));
    1591             : 
    1592          10 :     scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
    1593             :                               NULL, 2, key);
    1594             : 
    1595             :     /* Delete all the matching tuples */
    1596          70 :     while ((atttup = systable_getnext(scan)) != NULL)
    1597          60 :         CatalogTupleDelete(attrel, &atttup->t_self);
    1598             : 
    1599             :     /* Clean up after the scan */
    1600          10 :     systable_endscan(scan);
    1601          10 :     table_close(attrel, RowExclusiveLock);
    1602          10 : }
    1603             : 
    1604             : /*
    1605             :  *      RemoveAttributeById
    1606             :  *
    1607             :  * This is the guts of ALTER TABLE DROP COLUMN: actually mark the attribute
    1608             :  * deleted in pg_attribute.  We also remove pg_statistic entries for it.
    1609             :  * (Everything else needed, such as getting rid of any pg_attrdef entry,
    1610             :  * is handled by dependency.c.)
    1611             :  */
    1612             : void
    1613        1286 : RemoveAttributeById(Oid relid, AttrNumber attnum)
    1614             : {
    1615             :     Relation    rel;
    1616             :     Relation    attr_rel;
    1617             :     HeapTuple   tuple;
    1618             :     Form_pg_attribute attStruct;
    1619             :     char        newattname[NAMEDATALEN];
    1620             : 
    1621             :     /*
    1622             :      * Grab an exclusive lock on the target table, which we will NOT release
    1623             :      * until end of transaction.  (In the simple case where we are directly
    1624             :      * dropping this column, ATExecDropColumn already did this ... but when
    1625             :      * cascading from a drop of some other object, we may not have any lock.)
    1626             :      */
    1627        1286 :     rel = relation_open(relid, AccessExclusiveLock);
    1628             : 
    1629        1286 :     attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
    1630             : 
    1631        1286 :     tuple = SearchSysCacheCopy2(ATTNUM,
    1632             :                                 ObjectIdGetDatum(relid),
    1633             :                                 Int16GetDatum(attnum));
    1634        1286 :     if (!HeapTupleIsValid(tuple))   /* shouldn't happen */
    1635           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
    1636             :              attnum, relid);
    1637        1286 :     attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
    1638             : 
    1639        1286 :     if (attnum < 0)
    1640             :     {
    1641             :         /* System attribute (probably OID) ... just delete the row */
    1642             : 
    1643           0 :         CatalogTupleDelete(attr_rel, &tuple->t_self);
    1644             :     }
    1645             :     else
    1646             :     {
    1647             :         /* Dropping user attributes is lots harder */
    1648             : 
    1649             :         /* Mark the attribute as dropped */
    1650        1286 :         attStruct->attisdropped = true;
    1651             : 
    1652             :         /*
    1653             :          * Set the type OID to invalid.  A dropped attribute's type link
    1654             :          * cannot be relied on (once the attribute is dropped, the type might
    1655             :          * be too). Fortunately we do not need the type row --- the only
    1656             :          * really essential information is the type's typlen and typalign,
    1657             :          * which are preserved in the attribute's attlen and attalign.  We set
    1658             :          * atttypid to zero here as a means of catching code that incorrectly
    1659             :          * expects it to be valid.
    1660             :          */
    1661        1286 :         attStruct->atttypid = InvalidOid;
    1662             : 
    1663             :         /* Remove any NOT NULL constraint the column may have */
    1664        1286 :         attStruct->attnotnull = false;
    1665             : 
    1666             :         /* We don't want to keep stats for it anymore */
    1667        1286 :         attStruct->attstattarget = 0;
    1668             : 
    1669             :         /* Unset this so no one tries to look up the generation expression */
    1670        1286 :         attStruct->attgenerated = '\0';
    1671             : 
    1672             :         /*
    1673             :          * Change the column name to something that isn't likely to conflict
    1674             :          */
    1675        1286 :         snprintf(newattname, sizeof(newattname),
    1676             :                  "........pg.dropped.%d........", attnum);
    1677        1286 :         namestrcpy(&(attStruct->attname), newattname);
    1678             : 
    1679             :         /* clear the missing value if any */
    1680        1286 :         if (attStruct->atthasmissing)
    1681             :         {
    1682             :             Datum       valuesAtt[Natts_pg_attribute];
    1683             :             bool        nullsAtt[Natts_pg_attribute];
    1684             :             bool        replacesAtt[Natts_pg_attribute];
    1685             : 
    1686             :             /* update the tuple - set atthasmissing and attmissingval */
    1687         208 :             MemSet(valuesAtt, 0, sizeof(valuesAtt));
    1688           8 :             MemSet(nullsAtt, false, sizeof(nullsAtt));
    1689           8 :             MemSet(replacesAtt, false, sizeof(replacesAtt));
    1690             : 
    1691           8 :             valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
    1692             :                 BoolGetDatum(false);
    1693           8 :             replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
    1694           8 :             valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
    1695           8 :             nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
    1696           8 :             replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
    1697             : 
    1698           8 :             tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
    1699             :                                       valuesAtt, nullsAtt, replacesAtt);
    1700             :         }
    1701             : 
    1702        1286 :         CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
    1703             :     }
    1704             : 
    1705             :     /*
    1706             :      * Because updating the pg_attribute row will trigger a relcache flush for
    1707             :      * the target relation, we need not do anything else to notify other
    1708             :      * backends of the change.
    1709             :      */
    1710             : 
    1711        1286 :     table_close(attr_rel, RowExclusiveLock);
    1712             : 
    1713        1286 :     if (attnum > 0)
    1714        1286 :         RemoveStatistics(relid, attnum);
    1715             : 
    1716        1286 :     relation_close(rel, NoLock);
    1717        1286 : }
    1718             : 
    1719             : /*
    1720             :  *      RemoveAttrDefault
    1721             :  *
    1722             :  * If the specified relation/attribute has a default, remove it.
    1723             :  * (If no default, raise error if complain is true, else return quietly.)
    1724             :  */
    1725             : void
    1726         358 : RemoveAttrDefault(Oid relid, AttrNumber attnum,
    1727             :                   DropBehavior behavior, bool complain, bool internal)
    1728             : {
    1729             :     Relation    attrdef_rel;
    1730             :     ScanKeyData scankeys[2];
    1731             :     SysScanDesc scan;
    1732             :     HeapTuple   tuple;
    1733         358 :     bool        found = false;
    1734             : 
    1735         358 :     attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
    1736             : 
    1737         358 :     ScanKeyInit(&scankeys[0],
    1738             :                 Anum_pg_attrdef_adrelid,
    1739             :                 BTEqualStrategyNumber, F_OIDEQ,
    1740             :                 ObjectIdGetDatum(relid));
    1741         358 :     ScanKeyInit(&scankeys[1],
    1742             :                 Anum_pg_attrdef_adnum,
    1743             :                 BTEqualStrategyNumber, F_INT2EQ,
    1744             :                 Int16GetDatum(attnum));
    1745             : 
    1746         358 :     scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
    1747             :                               NULL, 2, scankeys);
    1748             : 
    1749             :     /* There should be at most one matching tuple, but we loop anyway */
    1750         610 :     while (HeapTupleIsValid(tuple = systable_getnext(scan)))
    1751             :     {
    1752             :         ObjectAddress object;
    1753         252 :         Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
    1754             : 
    1755         252 :         object.classId = AttrDefaultRelationId;
    1756         252 :         object.objectId = attrtuple->oid;
    1757         252 :         object.objectSubId = 0;
    1758             : 
    1759         252 :         performDeletion(&object, behavior,
    1760             :                         internal ? PERFORM_DELETION_INTERNAL : 0);
    1761             : 
    1762         252 :         found = true;
    1763             :     }
    1764             : 
    1765         358 :     systable_endscan(scan);
    1766         358 :     table_close(attrdef_rel, RowExclusiveLock);
    1767             : 
    1768         358 :     if (complain && !found)
    1769           0 :         elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
    1770             :              relid, attnum);
    1771         358 : }
    1772             : 
    1773             : /*
    1774             :  *      RemoveAttrDefaultById
    1775             :  *
    1776             :  * Remove a pg_attrdef entry specified by OID.  This is the guts of
    1777             :  * attribute-default removal.  Note it should be called via performDeletion,
    1778             :  * not directly.
    1779             :  */
    1780             : void
    1781        1438 : RemoveAttrDefaultById(Oid attrdefId)
    1782             : {
    1783             :     Relation    attrdef_rel;
    1784             :     Relation    attr_rel;
    1785             :     Relation    myrel;
    1786             :     ScanKeyData scankeys[1];
    1787             :     SysScanDesc scan;
    1788             :     HeapTuple   tuple;
    1789             :     Oid         myrelid;
    1790             :     AttrNumber  myattnum;
    1791             : 
    1792             :     /* Grab an appropriate lock on the pg_attrdef relation */
    1793        1438 :     attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
    1794             : 
    1795             :     /* Find the pg_attrdef tuple */
    1796        1438 :     ScanKeyInit(&scankeys[0],
    1797             :                 Anum_pg_attrdef_oid,
    1798             :                 BTEqualStrategyNumber, F_OIDEQ,
    1799             :                 ObjectIdGetDatum(attrdefId));
    1800             : 
    1801        1438 :     scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
    1802             :                               NULL, 1, scankeys);
    1803             : 
    1804        1438 :     tuple = systable_getnext(scan);
    1805        1438 :     if (!HeapTupleIsValid(tuple))
    1806           0 :         elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
    1807             : 
    1808        1438 :     myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
    1809        1438 :     myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
    1810             : 
    1811             :     /* Get an exclusive lock on the relation owning the attribute */
    1812        1438 :     myrel = relation_open(myrelid, AccessExclusiveLock);
    1813             : 
    1814             :     /* Now we can delete the pg_attrdef row */
    1815        1438 :     CatalogTupleDelete(attrdef_rel, &tuple->t_self);
    1816             : 
    1817        1438 :     systable_endscan(scan);
    1818        1438 :     table_close(attrdef_rel, RowExclusiveLock);
    1819             : 
    1820             :     /* Fix the pg_attribute row */
    1821        1438 :     attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
    1822             : 
    1823        1438 :     tuple = SearchSysCacheCopy2(ATTNUM,
    1824             :                                 ObjectIdGetDatum(myrelid),
    1825             :                                 Int16GetDatum(myattnum));
    1826        1438 :     if (!HeapTupleIsValid(tuple))   /* shouldn't happen */
    1827           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
    1828             :              myattnum, myrelid);
    1829             : 
    1830        1438 :     ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
    1831             : 
    1832        1438 :     CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
    1833             : 
    1834             :     /*
    1835             :      * Our update of the pg_attribute row will force a relcache rebuild, so
    1836             :      * there's nothing else to do here.
    1837             :      */
    1838        1438 :     table_close(attr_rel, RowExclusiveLock);
    1839             : 
    1840             :     /* Keep lock on attribute's rel until end of xact */
    1841        1438 :     relation_close(myrel, NoLock);
    1842        1438 : }
    1843             : 
    1844             : /*
    1845             :  * heap_drop_with_catalog   - removes specified relation from catalogs
    1846             :  *
    1847             :  * Note that this routine is not responsible for dropping objects that are
    1848             :  * linked to the pg_class entry via dependencies (for example, indexes and
    1849             :  * constraints).  Those are deleted by the dependency-tracing logic in
    1850             :  * dependency.c before control gets here.  In general, therefore, this routine
    1851             :  * should never be called directly; go through performDeletion() instead.
    1852             :  */
    1853             : void
    1854       23024 : heap_drop_with_catalog(Oid relid)
    1855             : {
    1856             :     Relation    rel;
    1857             :     HeapTuple   tuple;
    1858       23024 :     Oid         parentOid = InvalidOid,
    1859       23024 :                 defaultPartOid = InvalidOid;
    1860             : 
    1861             :     /*
    1862             :      * To drop a partition safely, we must grab exclusive lock on its parent,
    1863             :      * because another backend might be about to execute a query on the parent
    1864             :      * table.  If it relies on previously cached partition descriptor, then it
    1865             :      * could attempt to access the just-dropped relation as its partition. We
    1866             :      * must therefore take a table lock strong enough to prevent all queries
    1867             :      * on the table from proceeding until we commit and send out a
    1868             :      * shared-cache-inval notice that will make them update their partition
    1869             :      * descriptors.
    1870             :      */
    1871       23024 :     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1872       23024 :     if (!HeapTupleIsValid(tuple))
    1873           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
    1874       23024 :     if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
    1875             :     {
    1876        3454 :         parentOid = get_partition_parent(relid);
    1877        3454 :         LockRelationOid(parentOid, AccessExclusiveLock);
    1878             : 
    1879             :         /*
    1880             :          * If this is not the default partition, dropping it will change the
    1881             :          * default partition's partition constraint, so we must lock it.
    1882             :          */
    1883        3454 :         defaultPartOid = get_default_partition_oid(parentOid);
    1884        3454 :         if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
    1885         228 :             LockRelationOid(defaultPartOid, AccessExclusiveLock);
    1886             :     }
    1887             : 
    1888       23024 :     ReleaseSysCache(tuple);
    1889             : 
    1890             :     /*
    1891             :      * Open and lock the relation.
    1892             :      */
    1893       23024 :     rel = relation_open(relid, AccessExclusiveLock);
    1894             : 
    1895             :     /*
    1896             :      * There can no longer be anyone *else* touching the relation, but we
    1897             :      * might still have open queries or cursors, or pending trigger events, in
    1898             :      * our own session.
    1899             :      */
    1900       23024 :     CheckTableNotInUse(rel, "DROP TABLE");
    1901             : 
    1902             :     /*
    1903             :      * This effectively deletes all rows in the table, and may be done in a
    1904             :      * serializable transaction.  In that case we must record a rw-conflict in
    1905             :      * to this transaction from each transaction holding a predicate lock on
    1906             :      * the table.
    1907             :      */
    1908       23024 :     CheckTableForSerializableConflictIn(rel);
    1909             : 
    1910             :     /*
    1911             :      * Delete pg_foreign_table tuple first.
    1912             :      */
    1913       23024 :     if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
    1914             :     {
    1915             :         Relation    rel;
    1916             :         HeapTuple   tuple;
    1917             : 
    1918         118 :         rel = table_open(ForeignTableRelationId, RowExclusiveLock);
    1919             : 
    1920         118 :         tuple = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid));
    1921         118 :         if (!HeapTupleIsValid(tuple))
    1922           0 :             elog(ERROR, "cache lookup failed for foreign table %u", relid);
    1923             : 
    1924         118 :         CatalogTupleDelete(rel, &tuple->t_self);
    1925             : 
    1926         118 :         ReleaseSysCache(tuple);
    1927         118 :         table_close(rel, RowExclusiveLock);
    1928             :     }
    1929             : 
    1930             :     /*
    1931             :      * If a partitioned table, delete the pg_partitioned_table tuple.
    1932             :      */
    1933       23024 :     if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
    1934        1828 :         RemovePartitionKeyByRelId(relid);
    1935             : 
    1936             :     /*
    1937             :      * If the relation being dropped is the default partition itself,
    1938             :      * invalidate its entry in pg_partitioned_table.
    1939             :      */
    1940       23024 :     if (relid == defaultPartOid)
    1941         202 :         update_default_partition_oid(parentOid, InvalidOid);
    1942             : 
    1943             :     /*
    1944             :      * Schedule unlinking of the relation's physical files at commit.
    1945             :      */
    1946       23024 :     if (rel->rd_rel->relkind != RELKIND_VIEW &&
    1947       21916 :         rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
    1948       21704 :         rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
    1949       21586 :         rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
    1950             :     {
    1951       19758 :         RelationDropStorage(rel);
    1952             :     }
    1953             : 
    1954             :     /*
    1955             :      * Close relcache entry, but *keep* AccessExclusiveLock on the relation
    1956             :      * until transaction commit.  This ensures no one else will try to do
    1957             :      * something with the doomed relation.
    1958             :      */
    1959       23024 :     relation_close(rel, NoLock);
    1960             : 
    1961             :     /*
    1962             :      * Remove any associated relation synchronization states.
    1963             :      */
    1964       23024 :     RemoveSubscriptionRel(InvalidOid, relid);
    1965             : 
    1966             :     /*
    1967             :      * Forget any ON COMMIT action for the rel
    1968             :      */
    1969       23024 :     remove_on_commit_action(relid);
    1970             : 
    1971             :     /*
    1972             :      * Flush the relation from the relcache.  We want to do this before
    1973             :      * starting to remove catalog entries, just to be certain that no relcache
    1974             :      * entry rebuild will happen partway through.  (That should not really
    1975             :      * matter, since we don't do CommandCounterIncrement here, but let's be
    1976             :      * safe.)
    1977             :      */
    1978       23024 :     RelationForgetRelation(relid);
    1979             : 
    1980             :     /*
    1981             :      * remove inheritance information
    1982             :      */
    1983       23024 :     RelationRemoveInheritance(relid);
    1984             : 
    1985             :     /*
    1986             :      * delete statistics
    1987             :      */
    1988       23024 :     RemoveStatistics(relid, 0);
    1989             : 
    1990             :     /*
    1991             :      * delete attribute tuples
    1992             :      */
    1993       23024 :     DeleteAttributeTuples(relid);
    1994             : 
    1995             :     /*
    1996             :      * delete relation tuple
    1997             :      */
    1998       23024 :     DeleteRelationTuple(relid);
    1999             : 
    2000       23024 :     if (OidIsValid(parentOid))
    2001             :     {
    2002             :         /*
    2003             :          * If this is not the default partition, the partition constraint of
    2004             :          * the default partition has changed to include the portion of the key
    2005             :          * space previously covered by the dropped partition.
    2006             :          */
    2007        3454 :         if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
    2008         228 :             CacheInvalidateRelcacheByRelid(defaultPartOid);
    2009             : 
    2010             :         /*
    2011             :          * Invalidate the parent's relcache so that the partition is no longer
    2012             :          * included in its partition descriptor.
    2013             :          */
    2014        3454 :         CacheInvalidateRelcacheByRelid(parentOid);
    2015             :         /* keep the lock */
    2016             :     }
    2017       23024 : }
    2018             : 
    2019             : 
    2020             : /*
    2021             :  * RelationClearMissing
    2022             :  *
    2023             :  * Set atthasmissing and attmissingval to false/null for all attributes
    2024             :  * where they are currently set. This can be safely and usefully done if
    2025             :  * the table is rewritten (e.g. by VACUUM FULL or CLUSTER) where we know there
    2026             :  * are no rows left with less than a full complement of attributes.
    2027             :  *
    2028             :  * The caller must have an AccessExclusive lock on the relation.
    2029             :  */
    2030             : void
    2031        1026 : RelationClearMissing(Relation rel)
    2032             : {
    2033             :     Relation    attr_rel;
    2034        1026 :     Oid         relid = RelationGetRelid(rel);
    2035        1026 :     int         natts = RelationGetNumberOfAttributes(rel);
    2036             :     int         attnum;
    2037             :     Datum       repl_val[Natts_pg_attribute];
    2038             :     bool        repl_null[Natts_pg_attribute];
    2039             :     bool        repl_repl[Natts_pg_attribute];
    2040             :     Form_pg_attribute attrtuple;
    2041             :     HeapTuple   tuple,
    2042             :                 newtuple;
    2043             : 
    2044        1026 :     memset(repl_val, 0, sizeof(repl_val));
    2045        1026 :     memset(repl_null, false, sizeof(repl_null));
    2046        1026 :     memset(repl_repl, false, sizeof(repl_repl));
    2047             : 
    2048        1026 :     repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
    2049        1026 :     repl_null[Anum_pg_attribute_attmissingval - 1] = true;
    2050             : 
    2051        1026 :     repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
    2052        1026 :     repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
    2053             : 
    2054             : 
    2055             :     /* Get a lock on pg_attribute */
    2056        1026 :     attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
    2057             : 
    2058             :     /* process each non-system attribute, including any dropped columns */
    2059        4152 :     for (attnum = 1; attnum <= natts; attnum++)
    2060             :     {
    2061        3126 :         tuple = SearchSysCache2(ATTNUM,
    2062             :                                 ObjectIdGetDatum(relid),
    2063             :                                 Int16GetDatum(attnum));
    2064        3126 :         if (!HeapTupleIsValid(tuple))   /* shouldn't happen */
    2065           0 :             elog(ERROR, "cache lookup failed for attribute %d of relation %u",
    2066             :                  attnum, relid);
    2067             : 
    2068        3126 :         attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
    2069             : 
    2070             :         /* ignore any where atthasmissing is not true */
    2071        3126 :         if (attrtuple->atthasmissing)
    2072             :         {
    2073          64 :             newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
    2074             :                                          repl_val, repl_null, repl_repl);
    2075             : 
    2076          64 :             CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
    2077             : 
    2078          64 :             heap_freetuple(newtuple);
    2079             :         }
    2080             : 
    2081        3126 :         ReleaseSysCache(tuple);
    2082             :     }
    2083             : 
    2084             :     /*
    2085             :      * Our update of the pg_attribute rows will force a relcache rebuild, so
    2086             :      * there's nothing else to do here.
    2087             :      */
    2088        1026 :     table_close(attr_rel, RowExclusiveLock);
    2089        1026 : }
    2090             : 
    2091             : /*
    2092             :  * SetAttrMissing
    2093             :  *
    2094             :  * Set the missing value of a single attribute. This should only be used by
    2095             :  * binary upgrade. Takes an AccessExclusive lock on the relation owning the
    2096             :  * attribute.
    2097             :  */
    2098             : void
    2099           6 : SetAttrMissing(Oid relid, char *attname, char *value)
    2100             : {
    2101             :     Datum       valuesAtt[Natts_pg_attribute];
    2102             :     bool        nullsAtt[Natts_pg_attribute];
    2103             :     bool        replacesAtt[Natts_pg_attribute];
    2104             :     Datum       missingval;
    2105             :     Form_pg_attribute attStruct;
    2106             :     Relation    attrrel,
    2107             :                 tablerel;
    2108             :     HeapTuple   atttup,
    2109             :                 newtup;
    2110             : 
    2111             :     /* lock the table the attribute belongs to */
    2112           6 :     tablerel = table_open(relid, AccessExclusiveLock);
    2113             : 
    2114             :     /* Lock the attribute row and get the data */
    2115           6 :     attrrel = table_open(AttributeRelationId, RowExclusiveLock);
    2116           6 :     atttup = SearchSysCacheAttName(relid, attname);
    2117           6 :     if (!HeapTupleIsValid(atttup))
    2118           0 :         elog(ERROR, "cache lookup failed for attribute %s of relation %u",
    2119             :              attname, relid);
    2120           6 :     attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
    2121             : 
    2122             :     /* get an array value from the value string */
    2123           6 :     missingval = OidFunctionCall3(F_ARRAY_IN,
    2124             :                                   CStringGetDatum(value),
    2125             :                                   ObjectIdGetDatum(attStruct->atttypid),
    2126             :                                   Int32GetDatum(attStruct->atttypmod));
    2127             : 
    2128             :     /* update the tuple - set atthasmissing and attmissingval */
    2129         156 :     MemSet(valuesAtt, 0, sizeof(valuesAtt));
    2130           6 :     MemSet(nullsAtt, false, sizeof(nullsAtt));
    2131           6 :     MemSet(replacesAtt, false, sizeof(replacesAtt));
    2132             : 
    2133           6 :     valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
    2134           6 :     replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
    2135           6 :     valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
    2136           6 :     replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
    2137             : 
    2138           6 :     newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
    2139             :                                valuesAtt, nullsAtt, replacesAtt);
    2140           6 :     CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
    2141             : 
    2142             :     /* clean up */
    2143           6 :     ReleaseSysCache(atttup);
    2144           6 :     table_close(attrrel, RowExclusiveLock);
    2145           6 :     table_close(tablerel, AccessExclusiveLock);
    2146           6 : }
    2147             : 
    2148             : /*
    2149             :  * Store a default expression for column attnum of relation rel.
    2150             :  *
    2151             :  * Returns the OID of the new pg_attrdef tuple.
    2152             :  *
    2153             :  * add_column_mode must be true if we are storing the default for a new
    2154             :  * attribute, and false if it's for an already existing attribute. The reason
    2155             :  * for this is that the missing value must never be updated after it is set,
    2156             :  * which can only be when a column is added to the table. Otherwise we would
    2157             :  * in effect be changing existing tuples.
    2158             :  */
    2159             : Oid
    2160        1984 : StoreAttrDefault(Relation rel, AttrNumber attnum,
    2161             :                  Node *expr, bool is_internal, bool add_column_mode)
    2162             : {
    2163             :     char       *adbin;
    2164             :     Relation    adrel;
    2165             :     HeapTuple   tuple;
    2166             :     Datum       values[4];
    2167             :     static bool nulls[4] = {false, false, false, false};
    2168             :     Relation    attrrel;
    2169             :     HeapTuple   atttup;
    2170             :     Form_pg_attribute attStruct;
    2171             :     char        attgenerated;
    2172             :     Oid         attrdefOid;
    2173             :     ObjectAddress colobject,
    2174             :                 defobject;
    2175             : 
    2176        1984 :     adrel = table_open(AttrDefaultRelationId, RowExclusiveLock);
    2177             : 
    2178             :     /*
    2179             :      * Flatten expression to string form for storage.
    2180             :      */
    2181        1984 :     adbin = nodeToString(expr);
    2182             : 
    2183             :     /*
    2184             :      * Make the pg_attrdef entry.
    2185             :      */
    2186        1984 :     attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
    2187             :                                     Anum_pg_attrdef_oid);
    2188        1984 :     values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
    2189        1984 :     values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
    2190        1984 :     values[Anum_pg_attrdef_adnum - 1] = attnum;
    2191        1984 :     values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
    2192             : 
    2193        1984 :     tuple = heap_form_tuple(adrel->rd_att, values, nulls);
    2194        1984 :     CatalogTupleInsert(adrel, tuple);
    2195             : 
    2196        1984 :     defobject.classId = AttrDefaultRelationId;
    2197        1984 :     defobject.objectId = attrdefOid;
    2198        1984 :     defobject.objectSubId = 0;
    2199             : 
    2200        1984 :     table_close(adrel, RowExclusiveLock);
    2201             : 
    2202             :     /* now can free some of the stuff allocated above */
    2203        1984 :     pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
    2204        1984 :     heap_freetuple(tuple);
    2205        1984 :     pfree(adbin);
    2206             : 
    2207             :     /*
    2208             :      * Update the pg_attribute entry for the column to show that a default
    2209             :      * exists.
    2210             :      */
    2211        1984 :     attrrel = table_open(AttributeRelationId, RowExclusiveLock);
    2212        1984 :     atttup = SearchSysCacheCopy2(ATTNUM,
    2213             :                                  ObjectIdGetDatum(RelationGetRelid(rel)),
    2214             :                                  Int16GetDatum(attnum));
    2215        1984 :     if (!HeapTupleIsValid(atttup))
    2216           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
    2217             :              attnum, RelationGetRelid(rel));
    2218        1984 :     attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
    2219        1984 :     attgenerated = attStruct->attgenerated;
    2220        1984 :     if (!attStruct->atthasdef)
    2221             :     {
    2222             :         Form_pg_attribute defAttStruct;
    2223             : 
    2224             :         ExprState  *exprState;
    2225        1984 :         Expr       *expr2 = (Expr *) expr;
    2226        1984 :         EState     *estate = NULL;
    2227             :         ExprContext *econtext;
    2228             :         Datum       valuesAtt[Natts_pg_attribute];
    2229             :         bool        nullsAtt[Natts_pg_attribute];
    2230             :         bool        replacesAtt[Natts_pg_attribute];
    2231        1984 :         Datum       missingval = (Datum) 0;
    2232        1984 :         bool        missingIsNull = true;
    2233             : 
    2234       51584 :         MemSet(valuesAtt, 0, sizeof(valuesAtt));
    2235        1984 :         MemSet(nullsAtt, false, sizeof(nullsAtt));
    2236        1984 :         MemSet(replacesAtt, false, sizeof(replacesAtt));
    2237        1984 :         valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
    2238        1984 :         replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
    2239             : 
    2240        1984 :         if (add_column_mode && !attgenerated)
    2241             :         {
    2242         326 :             expr2 = expression_planner(expr2);
    2243         326 :             estate = CreateExecutorState();
    2244         326 :             exprState = ExecPrepareExpr(expr2, estate);
    2245         326 :             econtext = GetPerTupleExprContext(estate);
    2246             : 
    2247         326 :             missingval = ExecEvalExpr(exprState, econtext,
    2248             :                                       &missingIsNull);
    2249             : 
    2250         326 :             FreeExecutorState(estate);
    2251             : 
    2252         326 :             defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
    2253             : 
    2254         326 :             if (missingIsNull)
    2255             :             {
    2256             :                 /* if the default evaluates to NULL, just store a NULL array */
    2257           0 :                 missingval = (Datum) 0;
    2258             :             }
    2259             :             else
    2260             :             {
    2261             :                 /* otherwise make a one-element array of the value */
    2262         326 :                 missingval = PointerGetDatum(construct_array(&missingval,
    2263             :                                                              1,
    2264             :                                                              defAttStruct->atttypid,
    2265             :                                                              defAttStruct->attlen,
    2266             :                                                              defAttStruct->attbyval,
    2267             :                                                              defAttStruct->attalign));
    2268             :             }
    2269             : 
    2270         326 :             valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
    2271         326 :             replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
    2272         326 :             valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
    2273         326 :             replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
    2274         326 :             nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
    2275             :         }
    2276        1984 :         atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
    2277             :                                    valuesAtt, nullsAtt, replacesAtt);
    2278             : 
    2279        1984 :         CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
    2280             : 
    2281        1984 :         if (!missingIsNull)
    2282         326 :             pfree(DatumGetPointer(missingval));
    2283             : 
    2284             :     }
    2285        1984 :     table_close(attrrel, RowExclusiveLock);
    2286        1984 :     heap_freetuple(atttup);
    2287             : 
    2288             :     /*
    2289             :      * Make a dependency so that the pg_attrdef entry goes away if the column
    2290             :      * (or whole table) is deleted.
    2291             :      */
    2292        1984 :     colobject.classId = RelationRelationId;
    2293        1984 :     colobject.objectId = RelationGetRelid(rel);
    2294        1984 :     colobject.objectSubId = attnum;
    2295             : 
    2296        1984 :     recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
    2297             : 
    2298             :     /*
    2299             :      * Record dependencies on objects used in the expression, too.
    2300             :      */
    2301        1984 :     if (attgenerated)
    2302             :     {
    2303             :         /*
    2304             :          * Generated column: Dropping anything that the generation expression
    2305             :          * refers to automatically drops the generated column.
    2306             :          */
    2307         276 :         recordDependencyOnSingleRelExpr(&colobject, expr, RelationGetRelid(rel),
    2308             :                                         DEPENDENCY_AUTO,
    2309             :                                         DEPENDENCY_AUTO, false);
    2310             :     }
    2311             :     else
    2312             :     {
    2313             :         /*
    2314             :          * Normal default: Dropping anything that the default refers to
    2315             :          * requires CASCADE and drops the default only.
    2316             :          */
    2317        1708 :         recordDependencyOnSingleRelExpr(&defobject, expr, RelationGetRelid(rel),
    2318             :                                         DEPENDENCY_NORMAL,
    2319             :                                         DEPENDENCY_NORMAL, false);
    2320             :     }
    2321             : 
    2322             :     /*
    2323             :      * Post creation hook for attribute defaults.
    2324             :      *
    2325             :      * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
    2326             :      * couple of deletion/creation of the attribute's default entry, so the
    2327             :      * callee should check existence of an older version of this entry if it
    2328             :      * needs to distinguish.
    2329             :      */
    2330        1984 :     InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
    2331             :                                   RelationGetRelid(rel), attnum, is_internal);
    2332             : 
    2333        1984 :     return attrdefOid;
    2334             : }
    2335             : 
    2336             : /*
    2337             :  * Store a check-constraint expression for the given relation.
    2338             :  *
    2339             :  * Caller is responsible for updating the count of constraints
    2340             :  * in the pg_class entry for the relation.
    2341             :  *
    2342             :  * The OID of the new constraint is returned.
    2343             :  */
    2344             : static Oid
    2345        1160 : StoreRelCheck(Relation rel, const char *ccname, Node *expr,
    2346             :               bool is_validated, bool is_local, int inhcount,
    2347             :               bool is_no_inherit, bool is_internal)
    2348             : {
    2349             :     char       *ccbin;
    2350             :     List       *varList;
    2351             :     int         keycount;
    2352             :     int16      *attNos;
    2353             :     Oid         constrOid;
    2354             : 
    2355             :     /*
    2356             :      * Flatten expression to string form for storage.
    2357             :      */
    2358        1160 :     ccbin = nodeToString(expr);
    2359             : 
    2360             :     /*
    2361             :      * Find columns of rel that are used in expr
    2362             :      *
    2363             :      * NB: pull_var_clause is okay here only because we don't allow subselects
    2364             :      * in check constraints; it would fail to examine the contents of
    2365             :      * subselects.
    2366             :      */
    2367        1160 :     varList = pull_var_clause(expr, 0);
    2368        1160 :     keycount = list_length(varList);
    2369             : 
    2370        1160 :     if (keycount > 0)
    2371             :     {
    2372             :         ListCell   *vl;
    2373        1154 :         int         i = 0;
    2374             : 
    2375        1154 :         attNos = (int16 *) palloc(keycount * sizeof(int16));
    2376        2574 :         foreach(vl, varList)
    2377             :         {
    2378        1420 :             Var        *var = (Var *) lfirst(vl);
    2379             :             int         j;
    2380             : 
    2381        1540 :             for (j = 0; j < i; j++)
    2382         276 :                 if (attNos[j] == var->varattno)
    2383         156 :                     break;
    2384        1420 :             if (j == i)
    2385        1264 :                 attNos[i++] = var->varattno;
    2386             :         }
    2387        1154 :         keycount = i;
    2388             :     }
    2389             :     else
    2390           6 :         attNos = NULL;
    2391             : 
    2392             :     /*
    2393             :      * Partitioned tables do not contain any rows themselves, so a NO INHERIT
    2394             :      * constraint makes no sense.
    2395             :      */
    2396        1160 :     if (is_no_inherit &&
    2397          72 :         rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
    2398          16 :         ereport(ERROR,
    2399             :                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    2400             :                  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
    2401             :                         RelationGetRelationName(rel))));
    2402             : 
    2403             :     /*
    2404             :      * Create the Check Constraint
    2405             :      */
    2406             :     constrOid =
    2407        2288 :         CreateConstraintEntry(ccname,   /* Constraint Name */
    2408        1144 :                               RelationGetNamespace(rel),    /* namespace */
    2409             :                               CONSTRAINT_CHECK, /* Constraint Type */
    2410             :                               false,    /* Is Deferrable */
    2411             :                               false,    /* Is Deferred */
    2412             :                               is_validated,
    2413             :                               InvalidOid,   /* no parent constraint */
    2414             :                               RelationGetRelid(rel),    /* relation */
    2415             :                               attNos,   /* attrs in the constraint */
    2416             :                               keycount, /* # key attrs in the constraint */
    2417             :                               keycount, /* # total attrs in the constraint */
    2418             :                               InvalidOid,   /* not a domain constraint */
    2419             :                               InvalidOid,   /* no associated index */
    2420             :                               InvalidOid,   /* Foreign key fields */
    2421             :                               NULL,
    2422             :                               NULL,
    2423             :                               NULL,
    2424             :                               NULL,
    2425             :                               0,
    2426             :                               ' ',
    2427             :                               ' ',
    2428             :                               ' ',
    2429             :                               NULL, /* not an exclusion constraint */
    2430             :                               expr, /* Tree form of check constraint */
    2431             :                               ccbin,    /* Binary form of check constraint */
    2432             :                               is_local, /* conislocal */
    2433             :                               inhcount, /* coninhcount */
    2434             :                               is_no_inherit,    /* connoinherit */
    2435             :                               is_internal); /* internally constructed? */
    2436             : 
    2437        1144 :     pfree(ccbin);
    2438             : 
    2439        1144 :     return constrOid;
    2440             : }
    2441             : 
    2442             : /*
    2443             :  * Store defaults and constraints (passed as a list of CookedConstraint).
    2444             :  *
    2445             :  * Each CookedConstraint struct is modified to store the new catalog tuple OID.
    2446             :  *
    2447             :  * NOTE: only pre-cooked expressions will be passed this way, which is to
    2448             :  * say expressions inherited from an existing relation.  Newly parsed
    2449             :  * expressions can be added later, by direct calls to StoreAttrDefault
    2450             :  * and StoreRelCheck (see AddRelationNewConstraints()).
    2451             :  */
    2452             : static void
    2453      112708 : StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
    2454             : {
    2455      112708 :     int         numchecks = 0;
    2456             :     ListCell   *lc;
    2457             : 
    2458      112708 :     if (cooked_constraints == NIL)
    2459      112486 :         return;                 /* nothing to do */
    2460             : 
    2461             :     /*
    2462             :      * Deparsing of constraint expressions will fail unless the just-created
    2463             :      * pg_attribute tuples for this relation are made visible.  So, bump the
    2464             :      * command counter.  CAUTION: this will cause a relcache entry rebuild.
    2465             :      */
    2466         222 :     CommandCounterIncrement();
    2467             : 
    2468         494 :     foreach(lc, cooked_constraints)
    2469             :     {
    2470         272 :         CookedConstraint *con = (CookedConstraint *) lfirst(lc);
    2471             : 
    2472         272 :         switch (con->contype)
    2473             :         {
    2474         176 :             case CONSTR_DEFAULT:
    2475         176 :                 con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
    2476             :                                                is_internal, false);
    2477         176 :                 break;
    2478          96 :             case CONSTR_CHECK:
    2479          96 :                 con->conoid =
    2480         384 :                     StoreRelCheck(rel, con->name, con->expr,
    2481         288 :                                   !con->skip_validation, con->is_local,
    2482          96 :                                   con->inhcount, con->is_no_inherit,
    2483          96 :                                   is_internal);
    2484          96 :                 numchecks++;
    2485          96 :                 break;
    2486           0 :             default:
    2487           0 :                 elog(ERROR, "unrecognized constraint type: %d",
    2488             :                      (int) con->contype);
    2489             :         }
    2490             :     }
    2491             : 
    2492         222 :     if (numchecks > 0)
    2493          84 :         SetRelationNumChecks(rel, numchecks);
    2494             : }
    2495             : 
    2496             : /*
    2497             :  * AddRelationNewConstraints
    2498             :  *
    2499             :  * Add new column default expressions and/or constraint check expressions
    2500             :  * to an existing relation.  This is defined to do both for efficiency in
    2501             :  * DefineRelation, but of course you can do just one or the other by passing
    2502             :  * empty lists.
    2503             :  *
    2504             :  * rel: relation to be modified
    2505             :  * newColDefaults: list of RawColumnDefault structures
    2506             :  * newConstraints: list of Constraint nodes
    2507             :  * allow_merge: true if check constraints may be merged with existing ones
    2508             :  * is_local: true if definition is local, false if it's inherited
    2509             :  * is_internal: true if result of some internal process, not a user request
    2510             :  *
    2511             :  * All entries in newColDefaults will be processed.  Entries in newConstraints
    2512             :  * will be processed only if they are CONSTR_CHECK type.
    2513             :  *
    2514             :  * Returns a list of CookedConstraint nodes that shows the cooked form of
    2515             :  * the default and constraint expressions added to the relation.
    2516             :  *
    2517             :  * NB: caller should have opened rel with AccessExclusiveLock, and should
    2518             :  * hold that lock till end of transaction.  Also, we assume the caller has
    2519             :  * done a CommandCounterIncrement if necessary to make the relation's catalog
    2520             :  * tuples visible.
    2521             :  */
    2522             : List *
    2523        2832 : AddRelationNewConstraints(Relation rel,
    2524             :                           List *newColDefaults,
    2525             :                           List *newConstraints,
    2526             :                           bool allow_merge,
    2527             :                           bool is_local,
    2528             :                           bool is_internal,
    2529             :                           const char *queryString)
    2530             : {
    2531        2832 :     List       *cookedConstraints = NIL;
    2532             :     TupleDesc   tupleDesc;
    2533             :     TupleConstr *oldconstr;
    2534             :     int         numoldchecks;
    2535             :     ParseState *pstate;
    2536             :     ParseNamespaceItem *nsitem;
    2537             :     int         numchecks;
    2538             :     List       *checknames;
    2539             :     ListCell   *cell;
    2540             :     Node       *expr;
    2541             :     CookedConstraint *cooked;
    2542             : 
    2543             :     /*
    2544             :      * Get info about existing constraints.
    2545             :      */
    2546        2832 :     tupleDesc = RelationGetDescr(rel);
    2547        2832 :     oldconstr = tupleDesc->constr;
    2548        2832 :     if (oldconstr)
    2549        2094 :         numoldchecks = oldconstr->num_check;
    2550             :     else
    2551         738 :         numoldchecks = 0;
    2552             : 
    2553             :     /*
    2554             :      * Create a dummy ParseState and insert the target relation as its sole
    2555             :      * rangetable entry.  We need a ParseState for transformExpr.
    2556             :      */
    2557        2832 :     pstate = make_parsestate(NULL);
    2558        2832 :     pstate->p_sourcetext = queryString;
    2559        2832 :     nsitem = addRangeTableEntryForRelation(pstate,
    2560             :                                            rel,
    2561             :                                            AccessShareLock,
    2562             :                                            NULL,
    2563             :                                            false,
    2564             :                                            true);
    2565        2832 :     addNSItemToQuery(pstate, nsitem, true, true, true);
    2566             : 
    2567             :     /*
    2568             :      * Process column default expressions.
    2569             :      */
    2570        4742 :     foreach(cell, newColDefaults)
    2571             :     {
    2572        1986 :         RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
    2573        1986 :         Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
    2574             :         Oid         defOid;
    2575             : 
    2576        3972 :         expr = cookDefault(pstate, colDef->raw_default,
    2577             :                            atp->atttypid, atp->atttypmod,
    2578        1986 :                            NameStr(atp->attname),
    2579        1986 :                            atp->attgenerated);
    2580             : 
    2581             :         /*
    2582             :          * If the expression is just a NULL constant, we do not bother to make
    2583             :          * an explicit pg_attrdef entry, since the default behavior is
    2584             :          * equivalent.  This applies to column defaults, but not for
    2585             :          * generation expressions.
    2586             :          *
    2587             :          * Note a nonobvious property of this test: if the column is of a
    2588             :          * domain type, what we'll get is not a bare null Const but a
    2589             :          * CoerceToDomain expr, so we will not discard the default.  This is
    2590             :          * critical because the column default needs to be retained to
    2591             :          * override any default that the domain might have.
    2592             :          */
    2593        1910 :         if (expr == NULL ||
    2594        1910 :             (!colDef->generated &&
    2595        1670 :              IsA(expr, Const) &&
    2596         858 :              castNode(Const, expr)->constisnull))
    2597         126 :             continue;
    2598             : 
    2599             :         /* If the DEFAULT is volatile we cannot use a missing value */
    2600        1784 :         if (colDef->missingMode && contain_volatile_functions((Node *) expr))
    2601          42 :             colDef->missingMode = false;
    2602             : 
    2603        1784 :         defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal,
    2604        1784 :                                   colDef->missingMode);
    2605             : 
    2606        1784 :         cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
    2607        1784 :         cooked->contype = CONSTR_DEFAULT;
    2608        1784 :         cooked->conoid = defOid;
    2609        1784 :         cooked->name = NULL;
    2610        1784 :         cooked->attnum = colDef->attnum;
    2611        1784 :         cooked->expr = expr;
    2612        1784 :         cooked->skip_validation = false;
    2613        1784 :         cooked->is_local = is_local;
    2614        1784 :         cooked->inhcount = is_local ? 0 : 1;
    2615        1784 :         cooked->is_no_inherit = false;
    2616        1784 :         cookedConstraints = lappend(cookedConstraints, cooked);
    2617             :     }
    2618             : 
    2619             :     /*
    2620             :      * Process constraint expressions.
    2621             :      */
    2622        2756 :     numchecks = numoldchecks;
    2623        2756 :     checknames = NIL;
    2624        3854 :     foreach(cell, newConstraints)
    2625             :     {
    2626        1150 :         Constraint *cdef = (Constraint *) lfirst(cell);
    2627             :         char       *ccname;
    2628             :         Oid         constrOid;
    2629             : 
    2630        1150 :         if (cdef->contype != CONSTR_CHECK)
    2631           0 :             continue;
    2632             : 
    2633        1150 :         if (cdef->raw_expr != NULL)
    2634             :         {
    2635             :             Assert(cdef->cooked_expr == NULL);
    2636             : 
    2637             :             /*
    2638             :              * Transform raw parsetree to executable expression, and verify
    2639             :              * it's valid as a CHECK constraint.
    2640             :              */
    2641        1102 :             expr = cookConstraint(pstate, cdef->raw_expr,
    2642        1102 :                                   RelationGetRelationName(rel));
    2643             :         }
    2644             :         else
    2645             :         {
    2646             :             Assert(cdef->cooked_expr != NULL);
    2647             : 
    2648             :             /*
    2649             :              * Here, we assume the parser will only pass us valid CHECK
    2650             :              * expressions, so we do no particular checking.
    2651             :              */
    2652          48 :             expr = stringToNode(cdef->cooked_expr);
    2653             :         }
    2654             : 
    2655             :         /*
    2656             :          * Check name uniqueness, or generate a name if none was given.
    2657             :          */
    2658        1130 :         if (cdef->conname != NULL)
    2659             :         {
    2660             :             ListCell   *cell2;
    2661             : 
    2662         844 :             ccname = cdef->conname;
    2663             :             /* Check against other new constraints */
    2664             :             /* Needed because we don't do CommandCounterIncrement in loop */
    2665         876 :             foreach(cell2, checknames)
    2666             :             {
    2667          32 :                 if (strcmp((char *) lfirst(cell2), ccname) == 0)
    2668           0 :                     ereport(ERROR,
    2669             :                             (errcode(ERRCODE_DUPLICATE_OBJECT),
    2670             :                              errmsg("check constraint \"%s\" already exists",
    2671             :                                     ccname)));
    2672             :             }
    2673             : 
    2674             :             /* save name for future checks */
    2675         844 :             checknames = lappend(checknames, ccname);
    2676             : 
    2677             :             /*
    2678             :              * Check against pre-existing constraints.  If we are allowed to
    2679             :              * merge with an existing constraint, there's no more to do here.
    2680             :              * (We omit the duplicate constraint from the result, which is
    2681             :              * what ATAddCheckConstraint wants.)
    2682             :              */
    2683         828 :             if (MergeWithExistingConstraint(rel, ccname, expr,
    2684             :                                             allow_merge, is_local,
    2685         844 :                                             cdef->initially_valid,
    2686         844 :                                             cdef->is_no_inherit))
    2687          50 :                 continue;
    2688             :         }
    2689             :         else
    2690             :         {
    2691             :             /*
    2692             :              * When generating a name, we want to create "tab_col_check" for a
    2693             :              * column constraint and "tab_check" for a table constraint.  We
    2694             :              * no longer have any info about the syntactic positioning of the
    2695             :              * constraint phrase, so we approximate this by seeing whether the
    2696             :              * expression references more than one column.  (If the user
    2697             :              * played by the rules, the result is the same...)
    2698             :              *
    2699             :              * Note: pull_var_clause() doesn't descend into sublinks, but we
    2700             :              * eliminated those above; and anyway this only needs to be an
    2701             :              * approximate answer.
    2702             :              */
    2703             :             List       *vars;
    2704             :             char       *colname;
    2705             : 
    2706         286 :             vars = pull_var_clause(expr, 0);
    2707             : 
    2708             :             /* eliminate duplicates */
    2709         286 :             vars = list_union(NIL, vars);
    2710             : 
    2711         286 :             if (list_length(vars) == 1)
    2712         258 :                 colname = get_attname(RelationGetRelid(rel),
    2713         258 :                                       ((Var *) linitial(vars))->varattno,
    2714             :                                       true);
    2715             :             else
    2716          28 :                 colname = NULL;
    2717             : 
    2718         286 :             ccname = ChooseConstraintName(RelationGetRelationName(rel),
    2719             :                                           colname,
    2720             :                                           "check",
    2721         286 :                                           RelationGetNamespace(rel),
    2722             :                                           checknames);
    2723             : 
    2724             :             /* save name for future checks */
    2725         286 :             checknames = lappend(checknames, ccname);
    2726             :         }
    2727             : 
    2728             :         /*
    2729             :          * OK, store it.
    2730             :          */
    2731             :         constrOid =
    2732        2128 :             StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
    2733        1064 :                           is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
    2734             : 
    2735        1048 :         numchecks++;
    2736             : 
    2737        1048 :         cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
    2738        1048 :         cooked->contype = CONSTR_CHECK;
    2739        1048 :         cooked->conoid = constrOid;
    2740        1048 :         cooked->name = ccname;
    2741        1048 :         cooked->attnum = 0;
    2742        1048 :         cooked->expr = expr;
    2743        1048 :         cooked->skip_validation = cdef->skip_validation;
    2744        1048 :         cooked->is_local = is_local;
    2745        1048 :         cooked->inhcount = is_local ? 0 : 1;
    2746        1048 :         cooked->is_no_inherit = cdef->is_no_inherit;
    2747        1048 :         cookedConstraints = lappend(cookedConstraints, cooked);
    2748             :     }
    2749             : 
    2750             :     /*
    2751             :      * Update the count of constraints in the relation's pg_class tuple. We do
    2752             :      * this even if there was no change, in order to ensure that an SI update
    2753             :      * message is sent out for the pg_class tuple, which will force other
    2754             :      * backends to rebuild their relcache entries for the rel. (This is
    2755             :      * critical if we added defaults but not constraints.)
    2756             :      */
    2757        2704 :     SetRelationNumChecks(rel, numchecks);
    2758             : 
    2759        2704 :     return cookedConstraints;
    2760             : }
    2761             : 
    2762             : /*
    2763             :  * Check for a pre-existing check constraint that conflicts with a proposed
    2764             :  * new one, and either adjust its conislocal/coninhcount settings or throw
    2765             :  * error as needed.
    2766             :  *
    2767             :  * Returns true if merged (constraint is a duplicate), or false if it's
    2768             :  * got a so-far-unique name, or throws error if conflict.
    2769             :  *
    2770             :  * XXX See MergeConstraintsIntoExisting too if you change this code.
    2771             :  */
    2772             : static bool
    2773         844 : MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
    2774             :                             bool allow_merge, bool is_local,
    2775             :                             bool is_initially_valid,
    2776             :                             bool is_no_inherit)
    2777             : {
    2778             :     bool        found;
    2779             :     Relation    conDesc;
    2780             :     SysScanDesc conscan;
    2781             :     ScanKeyData skey[3];
    2782             :     HeapTuple   tup;
    2783             : 
    2784             :     /* Search for a pg_constraint entry with same name and relation */
    2785         844 :     conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
    2786             : 
    2787         844 :     found = false;
    2788             : 
    2789         844 :     ScanKeyInit(&skey[0],
    2790             :                 Anum_pg_constraint_conrelid,
    2791             :                 BTEqualStrategyNumber, F_OIDEQ,
    2792         844 :                 ObjectIdGetDatum(RelationGetRelid(rel)));
    2793         844 :     ScanKeyInit(&skey[1],
    2794             :                 Anum_pg_constraint_contypid,
    2795             :                 BTEqualStrategyNumber, F_OIDEQ,
    2796             :                 ObjectIdGetDatum(InvalidOid));
    2797         844 :     ScanKeyInit(&skey[2],
    2798             :                 Anum_pg_constraint_conname,
    2799             :                 BTEqualStrategyNumber, F_NAMEEQ,
    2800             :                 CStringGetDatum(ccname));
    2801             : 
    2802         844 :     conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId, true,
    2803             :                                  NULL, 3, skey);
    2804             : 
    2805             :     /* There can be at most one matching row */
    2806         844 :     if (HeapTupleIsValid(tup = systable_getnext(conscan)))
    2807             :     {
    2808          66 :         Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
    2809             : 
    2810             :         /* Found it.  Conflicts if not identical check constraint */
    2811          66 :         if (con->contype == CONSTRAINT_CHECK)
    2812             :         {
    2813             :             Datum       val;
    2814             :             bool        isnull;
    2815             : 
    2816          62 :             val = fastgetattr(tup,
    2817             :                               Anum_pg_constraint_conbin,
    2818             :                               conDesc->rd_att, &isnull);
    2819          62 :             if (isnull)
    2820           0 :                 elog(ERROR, "null conbin for rel %s",
    2821             :                      RelationGetRelationName(rel));
    2822          62 :             if (equal(expr, stringToNode(TextDatumGetCString(val))))
    2823          58 :                 found = true;
    2824             :         }
    2825             : 
    2826             :         /*
    2827             :          * If the existing constraint is purely inherited (no local
    2828             :          * definition) then interpret addition of a local constraint as a
    2829             :          * legal merge.  This allows ALTER ADD CONSTRAINT on parent and child
    2830             :          * tables to be given in either order with same end state.  However if
    2831             :          * the relation is a partition, all inherited constraints are always
    2832             :          * non-local, including those that were merged.
    2833             :          */
    2834          66 :         if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
    2835          24 :             allow_merge = true;
    2836             : 
    2837          66 :         if (!found || !allow_merge)
    2838           8 :             ereport(ERROR,
    2839             :                     (errcode(ERRCODE_DUPLICATE_OBJECT),
    2840             :                      errmsg("constraint \"%s\" for relation \"%s\" already exists",
    2841             :                             ccname, RelationGetRelationName(rel))));
    2842             : 
    2843             :         /* If the child constraint is "no inherit" then cannot merge */
    2844          58 :         if (con->connoinherit)
    2845           0 :             ereport(ERROR,
    2846             :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2847             :                      errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
    2848             :                             ccname, RelationGetRelationName(rel))));
    2849             : 
    2850             :         /*
    2851             :          * Must not change an existing inherited constraint to "no inherit"
    2852             :          * status.  That's because inherited constraints should be able to
    2853             :          * propagate to lower-level children.
    2854             :          */
    2855          58 :         if (con->coninhcount > 0 && is_no_inherit)
    2856           4 :             ereport(ERROR,
    2857             :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2858             :                      errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
    2859             :                             ccname, RelationGetRelationName(rel))));
    2860             : 
    2861             :         /*
    2862             :          * If the child constraint is "not valid" then cannot merge with a
    2863             :          * valid parent constraint.
    2864             :          */
    2865          54 :         if (is_initially_valid && !con->convalidated)
    2866           4 :             ereport(ERROR,
    2867             :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2868             :                      errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
    2869             :                             ccname, RelationGetRelationName(rel))));
    2870             : 
    2871             :         /* OK to update the tuple */
    2872          50 :         ereport(NOTICE,
    2873             :                 (errmsg("merging constraint \"%s\" with inherited definition",
    2874             :                         ccname)));
    2875             : 
    2876          50 :         tup = heap_copytuple(tup);
    2877          50 :         con = (Form_pg_constraint) GETSTRUCT(tup);
    2878             : 
    2879             :         /*
    2880             :          * In case of partitions, an inherited constraint must be inherited
    2881             :          * only once since it cannot have multiple parents and it is never
    2882             :          * considered local.
    2883             :          */
    2884          50 :         if (rel->rd_rel->relispartition)
    2885             :         {
    2886           8 :             con->coninhcount = 1;
    2887           8 :             con->conislocal = false;
    2888             :         }
    2889             :         else
    2890             :         {
    2891          42 :             if (is_local)
    2892          20 :                 con->conislocal = true;
    2893             :             else
    2894          22 :                 con->coninhcount++;
    2895             :         }
    2896             : 
    2897          50 :         if (is_no_inherit)
    2898             :         {
    2899             :             Assert(is_local);
    2900           0 :             con->connoinherit = true;
    2901             :         }
    2902             : 
    2903          50 :         CatalogTupleUpdate(conDesc, &tup->t_self, tup);
    2904             :     }
    2905             : 
    2906         828 :     systable_endscan(conscan);
    2907         828 :     table_close(conDesc, RowExclusiveLock);
    2908             : 
    2909         828 :     return found;
    2910             : }
    2911             : 
    2912             : /*
    2913             :  * Update the count of constraints in the relation's pg_class tuple.
    2914             :  *
    2915             :  * Caller had better hold exclusive lock on the relation.
    2916             :  *
    2917             :  * An important side effect is that a SI update message will be sent out for
    2918             :  * the pg_class tuple, which will force other backends to rebuild their
    2919             :  * relcache entries for the rel.  Also, this backend will rebuild its
    2920             :  * own relcache entry at the next CommandCounterIncrement.
    2921             :  */
    2922             : static void
    2923        2788 : SetRelationNumChecks(Relation rel, int numchecks)
    2924             : {
    2925             :     Relation    relrel;
    2926             :     HeapTuple   reltup;
    2927             :     Form_pg_class relStruct;
    2928             : 
    2929        2788 :     relrel = table_open(RelationRelationId, RowExclusiveLock);
    2930        2788 :     reltup = SearchSysCacheCopy1(RELOID,
    2931             :                                  ObjectIdGetDatum(RelationGetRelid(rel)));
    2932        2788 :     if (!HeapTupleIsValid(reltup))
    2933           0 :         elog(ERROR, "cache lookup failed for relation %u",
    2934             :              RelationGetRelid(rel));
    2935        2788 :     relStruct = (Form_pg_class) GETSTRUCT(reltup);
    2936             : 
    2937        2788 :     if (relStruct->relchecks != numchecks)
    2938             :     {
    2939        1074 :         relStruct->relchecks = numchecks;
    2940             : 
    2941        1074 :         CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
    2942             :     }
    2943             :     else
    2944             :     {
    2945             :         /* Skip the disk update, but force relcache inval anyway */
    2946        1714 :         CacheInvalidateRelcache(rel);
    2947             :     }
    2948             : 
    2949        2788 :     heap_freetuple(reltup);
    2950        2788 :     table_close(relrel, RowExclusiveLock);
    2951        2788 : }
    2952             : 
    2953             : /*
    2954             :  * Check for references to generated columns
    2955             :  */
    2956             : static bool
    2957         772 : check_nested_generated_walker(Node *node, void *context)
    2958             : {
    2959         772 :     ParseState *pstate = context;
    2960             : 
    2961         772 :     if (node == NULL)
    2962           0 :         return false;
    2963         772 :     else if (IsA(node, Var))
    2964             :     {
    2965         258 :         Var        *var = (Var *) node;
    2966             :         Oid         relid;
    2967             :         AttrNumber  attnum;
    2968             : 
    2969         258 :         relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
    2970         258 :         attnum = var->varattno;
    2971             : 
    2972         258 :         if (OidIsValid(relid) && AttributeNumberIsValid(attnum) && get_attgenerated(relid, attnum))
    2973          12 :             ereport(ERROR,
    2974             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    2975             :                      errmsg("cannot use generated column \"%s\" in column generation expression",
    2976             :                             get_attname(relid, attnum, false)),
    2977             :                      errdetail("A generated column cannot reference another generated column."),
    2978             :                      parser_errposition(pstate, var->location)));
    2979             : 
    2980         246 :         return false;
    2981             :     }
    2982             :     else
    2983         514 :         return expression_tree_walker(node, check_nested_generated_walker,
    2984             :                                       (void *) context);
    2985             : }
    2986             : 
    2987             : static void
    2988         256 : check_nested_generated(ParseState *pstate, Node *node)
    2989             : {
    2990         256 :     check_nested_generated_walker(node, pstate);
    2991         244 : }
    2992             : 
    2993             : /*
    2994             :  * Take a raw default and convert it to a cooked format ready for
    2995             :  * storage.
    2996             :  *
    2997             :  * Parse state should be set up to recognize any vars that might appear
    2998             :  * in the expression.  (Even though we plan to reject vars, it's more
    2999             :  * user-friendly to give the correct error message than "unknown var".)
    3000             :  *
    3001             :  * If atttypid is not InvalidOid, coerce the expression to the specified
    3002             :  * type (and typmod atttypmod).   attname is only needed in this case:
    3003             :  * it is used in the error message, if any.
    3004             :  */
    3005             : Node *
    3006        2378 : cookDefault(ParseState *pstate,
    3007             :             Node *raw_default,
    3008             :             Oid atttypid,
    3009             :             int32 atttypmod,
    3010             :             const char *attname,
    3011             :             char attgenerated)
    3012             : {
    3013             :     Node       *expr;
    3014             : 
    3015             :     Assert(raw_default != NULL);
    3016             : 
    3017             :     /*
    3018             :      * Transform raw parsetree to executable expression.
    3019             :      */
    3020        2378 :     expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
    3021             : 
    3022        2322 :     if (attgenerated)
    3023             :     {
    3024         256 :         check_nested_generated(pstate, expr);
    3025             : 
    3026         244 :         if (contain_mutable_functions(expr))
    3027           4 :             ereport(ERROR,
    3028             :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    3029             :                      errmsg("generation expression is not immutable")));
    3030             :     }
    3031             :     else
    3032             :     {
    3033             :         /*
    3034             :          * For a default expression, transformExpr() should have rejected
    3035             :          * column references.
    3036             :          */
    3037             :         Assert(!contain_var_clause(expr));
    3038             :     }
    3039             : 
    3040             :     /*
    3041             :      * Coerce the expression to the correct type and typmod, if given. This
    3042             :      * should match the parser's processing of non-defaulted expressions ---
    3043             :      * see transformAssignedExpr().
    3044             :      */
    3045        2306 :     if (OidIsValid(atttypid))
    3046             :     {
    3047        2306 :         Oid         type_id = exprType(expr);
    3048             : 
    3049        2306 :         expr = coerce_to_target_type(pstate, expr, type_id,
    3050             :                                      atttypid, atttypmod,
    3051             :                                      COERCION_ASSIGNMENT,
    3052             :                                      COERCE_IMPLICIT_CAST,
    3053             :                                      -1);
    3054        2302 :         if (expr == NULL)
    3055           0 :             ereport(ERROR,
    3056             :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
    3057             :                      errmsg("column \"%s\" is of type %s"
    3058             :                             " but default expression is of type %s",
    3059             :                             attname,
    3060             :                             format_type_be(atttypid),
    3061             :                             format_type_be(type_id)),
    3062             :                      errhint("You will need to rewrite or cast the expression.")));
    3063             :     }
    3064             : 
    3065             :     /*
    3066             :      * Finally, take care of collations in the finished expression.
    3067             :      */
    3068        2302 :     assign_expr_collations(pstate, expr);
    3069             : 
    3070        2302 :     return expr;
    3071             : }
    3072             : 
    3073             : /*
    3074             :  * Take a raw CHECK constraint expression and convert it to a cooked format
    3075             :  * ready for storage.
    3076             :  *
    3077             :  * Parse state must be set up to recognize any vars that might appear
    3078             :  * in the expression.
    3079             :  */
    3080             : static Node *
    3081        1102 : cookConstraint(ParseState *pstate,
    3082             :                Node *raw_constraint,
    3083             :                char *relname)
    3084             : {
    3085             :     Node       *expr;
    3086             : 
    3087             :     /*
    3088             :      * Transform raw parsetree to executable expression.
    3089             :      */
    3090        1102 :     expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
    3091             : 
    3092             :     /*
    3093             :      * Make sure it yields a boolean result.
    3094             :      */
    3095        1082 :     expr = coerce_to_boolean(pstate, expr, "CHECK");
    3096             : 
    3097             :     /*
    3098             :      * Take care of collations.
    3099             :      */
    3100        1082 :     assign_expr_collations(pstate, expr);
    3101             : 
    3102             :     /*
    3103             :      * Make sure no outside relations are referred to (this is probably dead
    3104             :      * code now that add_missing_from is history).
    3105             :      */
    3106        1082 :     if (list_length(pstate->p_rtable) != 1)
    3107           0 :         ereport(ERROR,
    3108             :                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    3109             :                  errmsg("only table \"%s\" can be referenced in check constraint",
    3110             :                         relname)));
    3111             : 
    3112        1082 :     return expr;
    3113             : }
    3114             : 
    3115             : 
    3116             : /*
    3117             :  * RemoveStatistics --- remove entries in pg_statistic for a rel or column
    3118             :  *
    3119             :  * If attnum is zero, remove all entries for rel; else remove only the one(s)
    3120             :  * for that column.
    3121             :  */
    3122             : void
    3123       25178 : RemoveStatistics(Oid relid, AttrNumber attnum)
    3124             : {
    3125             :     Relation    pgstatistic;
    3126             :     SysScanDesc scan;
    3127             :     ScanKeyData key[2];
    3128             :     int         nkeys;
    3129             :     HeapTuple   tuple;
    3130             : 
    3131       25178 :     pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
    3132             : 
    3133       25178 :     ScanKeyInit(&key[0],
    3134             :                 Anum_pg_statistic_starelid,
    3135             :                 BTEqualStrategyNumber, F_OIDEQ,
    3136             :                 ObjectIdGetDatum(relid));
    3137             : 
    3138       25178 :     if (attnum == 0)
    3139       23340 :         nkeys = 1;
    3140             :     else
    3141             :     {
    3142        1838 :         ScanKeyInit(&key[1],
    3143             :                     Anum_pg_statistic_staattnum,
    3144             :                     BTEqualStrategyNumber, F_INT2EQ,
    3145             :                     Int16GetDatum(attnum));
    3146        1838 :         nkeys = 2;
    3147             :     }
    3148             : 
    3149       25178 :     scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
    3150             :                               NULL, nkeys, key);
    3151             : 
    3152             :     /* we must loop even when attnum != 0, in case of inherited stats */
    3153       26562 :     while (HeapTupleIsValid(tuple = systable_getnext(scan)))
    3154        1384 :         CatalogTupleDelete(pgstatistic, &tuple->t_self);
    3155             : 
    3156       25178 :     systable_endscan(scan);
    3157             : 
    3158       25178 :     table_close(pgstatistic, RowExclusiveLock);
    3159       25178 : }
    3160             : 
    3161             : 
    3162             : /*
    3163             :  * RelationTruncateIndexes - truncate all indexes associated
    3164             :  * with the heap relation to zero tuples.
    3165             :  *
    3166             :  * The routine will truncate and then reconstruct the indexes on
    3167             :  * the specified relation.  Caller must hold exclusive lock on rel.
    3168             :  */
    3169             : static void
    3170         396 : RelationTruncateIndexes(Relation heapRelation)
    3171             : {
    3172             :     ListCell   *indlist;
    3173             : 
    3174             :     /* Ask the relcache to produce a list of the indexes of the rel */
    3175         524 :     foreach(indlist, RelationGetIndexList(heapRelation))
    3176             :     {
    3177         128 :         Oid         indexId = lfirst_oid(indlist);
    3178             :         Relation    currentIndex;
    3179             :         IndexInfo  *indexInfo;
    3180             : 
    3181             :         /* Open the index relation; use exclusive lock, just to be sure */
    3182         128 :         currentIndex = index_open(indexId, AccessExclusiveLock);
    3183             : 
    3184             :         /*
    3185             :          * Fetch info needed for index_build.  Since we know there are no
    3186             :          * tuples that actually need indexing, we can use a dummy IndexInfo.
    3187             :          * This is slightly cheaper to build, but the real point is to avoid
    3188             :          * possibly running user-defined code in index expressions or
    3189             :          * predicates.  We might be getting invoked during ON COMMIT
    3190             :          * processing, and we don't want to run any such code then.
    3191             :          */
    3192         128 :         indexInfo = BuildDummyIndexInfo(currentIndex);
    3193             : 
    3194             :         /*
    3195             :          * Now truncate the actual file (and discard buffers).
    3196             :          */
    3197         128 :         RelationTruncate(currentIndex, 0);
    3198             : 
    3199             :         /* Initialize the index and rebuild */
    3200             :         /* Note: we do not need to re-establish pkey setting */
    3201         128 :         index_build(heapRelation, currentIndex, indexInfo, true, false);
    3202             : 
    3203             :         /* We're done with this index */
    3204         128 :         index_close(currentIndex, NoLock);
    3205             :     }
    3206         396 : }
    3207             : 
    3208             : /*
    3209             :  *   heap_truncate
    3210             :  *
    3211             :  *   This routine deletes all data within all the specified relations.
    3212             :  *
    3213             :  * This is not transaction-safe!  There is another, transaction-safe
    3214             :  * implementation in commands/tablecmds.c.  We now use this only for
    3215             :  * ON COMMIT truncation of temporary tables, where it doesn't matter.
    3216             :  */
    3217             : void
    3218         220 : heap_truncate(List *relids)
    3219             : {
    3220         220 :     List       *relations = NIL;
    3221             :     ListCell   *cell;
    3222             : 
    3223             :     /* Open relations for processing, and grab exclusive access on each */
    3224         484 :     foreach(cell, relids)
    3225             :     {
    3226         264 :         Oid         rid = lfirst_oid(cell);
    3227             :         Relation    rel;
    3228             : 
    3229         264 :         rel = table_open(rid, AccessExclusiveLock);
    3230         264 :         relations = lappend(relations, rel);
    3231             :     }
    3232             : 
    3233             :     /* Don't allow truncate on tables that are referenced by foreign keys */
    3234         220 :     heap_truncate_check_FKs(relations, true);
    3235             : 
    3236             :     /* OK to do it */
    3237         472 :     foreach(cell, relations)
    3238             :     {
    3239         256 :         Relation    rel = lfirst(cell);
    3240             : 
    3241             :         /* Truncate the relation */
    3242         256 :         heap_truncate_one_rel(rel);
    3243             : 
    3244             :         /* Close the relation, but keep exclusive lock on it until commit */
    3245         256 :         table_close(rel, NoLock);
    3246             :     }
    3247         216 : }
    3248             : 
    3249             : /*
    3250             :  *   heap_truncate_one_rel
    3251             :  *
    3252             :  *   This routine deletes all data within the specified relation.
    3253             :  *
    3254             :  * This is not transaction-safe, because the truncation is done immediately
    3255             :  * and cannot be rolled back later.  Caller is responsible for having
    3256             :  * checked permissions etc, and must have obtained AccessExclusiveLock.
    3257             :  */
    3258             : void
    3259         336 : heap_truncate_one_rel(Relation rel)
    3260             : {
    3261             :     Oid         toastrelid;
    3262             : 
    3263             :     /*
    3264             :      * Truncate the relation.  Partitioned tables have no storage, so there is
    3265             :      * nothing to do for them here.
    3266             :      */
    3267         336 :     if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
    3268          16 :         return;
    3269             : 
    3270             :     /* Truncate the underlying relation */
    3271         320 :     table_relation_nontransactional_truncate(rel);
    3272             : 
    3273             :     /* If the relation has indexes, truncate the indexes too */
    3274         320 :     RelationTruncateIndexes(rel);
    3275             : 
    3276             :     /* If there is a toast table, truncate that too */
    3277         320 :     toastrelid = rel->rd_rel->reltoastrelid;
    3278         320 :     if (OidIsValid(toastrelid))
    3279             :     {
    3280          76 :         Relation    toastrel = table_open(toastrelid, AccessExclusiveLock);
    3281             : 
    3282          76 :         table_relation_nontransactional_truncate(toastrel);
    3283          76 :         RelationTruncateIndexes(toastrel);
    3284             :         /* keep the lock... */
    3285          76 :         table_close(toastrel, NoLock);
    3286             :     }
    3287             : }
    3288             : 
    3289             : /*
    3290             :  * heap_truncate_check_FKs
    3291             :  *      Check for foreign keys referencing a list of relations that
    3292             :  *      are to be truncated, and raise error if there are any
    3293             :  *
    3294             :  * We disallow such FKs (except self-referential ones) since the whole point
    3295             :  * of TRUNCATE is to not scan the individual rows to be thrown away.
    3296             :  *
    3297             :  * This is split out so it can be shared by both implementations of truncate.
    3298             :  * Caller should already hold a suitable lock on the relations.
    3299             :  *
    3300             :  * tempTables is only used to select an appropriate error message.
    3301             :  */
    3302             : void
    3303         974 : heap_truncate_check_FKs(List *relations, bool tempTables)
    3304             : {
    3305         974 :     List       *oids = NIL;
    3306             :     List       *dependents;
    3307             :     ListCell   *cell;
    3308             : 
    3309             :     /*
    3310             :      * Build a list of OIDs of the interesting relations.
    3311             :      *
    3312             :      * If a relation has no triggers, then it can neither have FKs nor be
    3313             :      * referenced by a FK from another table, so we can ignore it.  For
    3314             :      * partitioned tables, FKs have no triggers, so we must include them
    3315             :      * anyway.
    3316             :      */
    3317        3206 :     foreach(cell, relations)
    3318             :     {
    3319        2232 :         Relation    rel = lfirst(cell);
    3320             : 
    3321        2232 :         if (rel->rd_rel->relhastriggers ||
    3322        1640 :             rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
    3323         956 :             oids = lappend_oid(oids, RelationGetRelid(rel));
    3324             :     }
    3325             : 
    3326             :     /*
    3327             :      * Fast path: if no relation has triggers, none has FKs either.
    3328             :      */
    3329         974 :     if (oids == NIL)
    3330         566 :         return;
    3331             : 
    3332             :     /*
    3333             :      * Otherwise, must scan pg_constraint.  We make one pass with all the
    3334             :      * relations considered; if this finds nothing, then all is well.
    3335             :      */
    3336         408 :     dependents = heap_truncate_find_FKs(oids);
    3337         408 :     if (dependents == NIL)
    3338         356 :         return;
    3339             : 
    3340             :     /*
    3341             :      * Otherwise we repeat the scan once per relation to identify a particular
    3342             :      * pair of relations to complain about.  This is pretty slow, but
    3343             :      * performance shouldn't matter much in a failure path.  The reason for
    3344             :      * doing things this way is to ensure that the message produced is not
    3345             :      * dependent on chance row locations within pg_constraint.
    3346             :      */
    3347          68 :     foreach(cell, oids)
    3348             :     {
    3349          68 :         Oid         relid = lfirst_oid(cell);
    3350             :         ListCell   *cell2;
    3351             : 
    3352          68 :         dependents = heap_truncate_find_FKs(list_make1_oid(relid));
    3353             : 
    3354         108 :         foreach(cell2, dependents)
    3355             :         {
    3356          92 :             Oid         relid2 = lfirst_oid(cell2);
    3357             : 
    3358          92 :             if (!list_member_oid(oids, relid2))
    3359             :             {
    3360          52 :                 char       *relname = get_rel_name(relid);
    3361          52 :                 char       *relname2 = get_rel_name(relid2);
    3362             : 
    3363          52 :                 if (tempTables)
    3364           4 :                     ereport(ERROR,
    3365             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3366             :                              errmsg("unsupported ON COMMIT and foreign key combination"),
    3367             :                              errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
    3368             :                                        relname2, relname)));
    3369             :                 else
    3370          48 :                     ereport(ERROR,
    3371             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3372             :                              errmsg("cannot truncate a table referenced in a foreign key constraint"),
    3373             :                              errdetail("Table \"%s\" references \"%s\".",
    3374             :                                        relname2, relname),
    3375             :                              errhint("Truncate table \"%s\" at the same time, "
    3376             :                                      "or use TRUNCATE ... CASCADE.",
    3377             :                                      relname2)));
    3378             :             }
    3379             :         }
    3380             :     }
    3381             : }
    3382             : 
    3383             : /*
    3384             :  * heap_truncate_find_FKs
    3385             :  *      Find relations having foreign keys referencing any of the given rels
    3386             :  *
    3387             :  * Input and result are both lists of relation OIDs.  The result contains
    3388             :  * no duplicates, does *not* include any rels that were already in the input
    3389             :  * list, and is sorted in OID order.  (The last property is enforced mainly
    3390             :  * to guarantee consistent behavior in the regression tests; we don't want
    3391             :  * behavior to change depending on chance locations of rows in pg_constraint.)
    3392             :  *
    3393             :  * Note: caller should already have appropriate lock on all rels mentioned
    3394             :  * in relationIds.  Since adding or dropping an FK requires exclusive lock
    3395             :  * on both rels, this ensures that the answer will be stable.
    3396             :  */
    3397             : List *
    3398         522 : heap_truncate_find_FKs(List *relationIds)
    3399             : {
    3400         522 :     List       *result = NIL;
    3401         522 :     List       *oids = list_copy(relationIds);
    3402             :     List       *parent_cons;
    3403             :     ListCell   *cell;
    3404             :     ScanKeyData key;
    3405             :     Relation    fkeyRel;
    3406             :     SysScanDesc fkeyScan;
    3407             :     HeapTuple   tuple;
    3408             :     bool        restart;
    3409             : 
    3410         522 :     oids = list_copy(relationIds);
    3411             : 
    3412             :     /*
    3413             :      * Must scan pg_constraint.  Right now, it is a seqscan because there is
    3414             :      * no available index on confrelid.
    3415             :      */
    3416         522 :     fkeyRel = table_open(ConstraintRelationId, AccessShareLock);
    3417             : 
    3418         538 : restart:
    3419         538 :     restart = false;
    3420         538 :     parent_cons = NIL;
    3421             : 
    3422         538 :     fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
    3423             :                                   NULL, 0, NULL);
    3424             : 
    3425       59822 :     while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
    3426             :     {
    3427       59284 :         Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
    3428             : 
    3429             :         /* Not a foreign key */
    3430       59284 :         if (con->contype != CONSTRAINT_FOREIGN)
    3431       38562 :             continue;
    3432             : 
    3433             :         /* Not referencing one of our list of tables */
    3434       20722 :         if (!list_member_oid(oids, con->confrelid))
    3435       20170 :             continue;
    3436             : 
    3437             :         /*
    3438             :          * If this constraint has a parent constraint which we have not seen
    3439             :          * yet, keep track of it for the second loop, below.  Tracking parent
    3440             :          * constraints allows us to climb up to the top-level level constraint
    3441             :          * and look for all possible relations referencing the partitioned
    3442             :          * table.
    3443             :          */
    3444         552 :         if (OidIsValid(con->conparentid) &&
    3445         128 :             !list_member_oid(parent_cons, con->conparentid))
    3446          80 :             parent_cons = lappend_oid(parent_cons, con->conparentid);
    3447             : 
    3448             :         /*
    3449             :          * Add referencer to result, unless present in input list.  (Don't
    3450             :          * worry about dupes: we'll fix that below).
    3451             :          */
    3452         552 :         if (!list_member_oid(relationIds, con->conrelid))
    3453         328 :             result = lappend_oid(result, con->conrelid);
    3454             :     }
    3455             : 
    3456         538 :     systable_endscan(fkeyScan);
    3457             : 
    3458             :     /*
    3459             :      * Process each parent constraint we found to add the list of referenced
    3460             :      * relations by them to the oids list.  If we do add any new such
    3461             :      * relations, redo the first loop above.  Also, if we see that the parent
    3462             :      * constraint in turn has a parent, add that so that we process all
    3463             :      * relations in a single additional pass.
    3464             :      */
    3465         626 :     foreach(cell, parent_cons)
    3466             :     {
    3467          88 :         Oid         parent = lfirst_oid(cell);
    3468             : 
    3469          88 :         ScanKeyInit(&key,
    3470             :                     Anum_pg_constraint_oid,
    3471             :                     BTEqualStrategyNumber, F_OIDEQ,
    3472             :                     ObjectIdGetDatum(parent));
    3473             : 
    3474          88 :         fkeyScan = systable_beginscan(fkeyRel, ConstraintOidIndexId,
    3475             :                                       true, NULL, 1, &key);
    3476             : 
    3477          88 :         tuple = systable_getnext(fkeyScan);
    3478          88 :         if (HeapTupleIsValid(tuple))
    3479             :         {
    3480          88 :             Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
    3481             : 
    3482             :             /*
    3483             :              * pg_constraint rows always appear for partitioned hierarchies
    3484             :              * this way: on the each side of the constraint, one row appears
    3485             :              * for each partition that points to the top-most table on the
    3486             :              * other side.
    3487             :              *
    3488             :              * Because of this arrangement, we can correctly catch all
    3489             :              * relevant relations by adding to 'parent_cons' all rows with
    3490             :              * valid conparentid, and to the 'oids' list all rows with a zero
    3491             :              * conparentid.  If any oids are added to 'oids', redo the first
    3492             :              * loop above by setting 'restart'.
    3493             :              */
    3494          88 :             if (OidIsValid(con->conparentid))
    3495          36 :                 parent_cons = list_append_unique_oid(parent_cons,
    3496             :                                                      con->conparentid);
    3497          52 :             else if (!list_member_oid(oids, con->confrelid))
    3498             :             {
    3499          16 :                 oids = lappend_oid(oids, con->confrelid);
    3500          16 :                 restart = true;
    3501             :             }
    3502             :         }
    3503             : 
    3504          88 :         systable_endscan(fkeyScan);
    3505             :     }
    3506             : 
    3507         538 :     list_free(parent_cons);
    3508         538 :     if (restart)
    3509          16 :         goto restart;
    3510             : 
    3511         522 :     table_close(fkeyRel, AccessShareLock);
    3512         522 :     list_free(oids);
    3513             : 
    3514             :     /* Now sort and de-duplicate the result list */
    3515         522 :     list_sort(result, list_oid_cmp);
    3516         522 :     list_deduplicate_oid(result);
    3517             : 
    3518         522 :     return result;
    3519             : }
    3520             : 
    3521             : /*
    3522             :  * StorePartitionKey
    3523             :  *      Store information about the partition key rel into the catalog
    3524             :  */
    3525             : void
    3526        2336 : StorePartitionKey(Relation rel,
    3527             :                   char strategy,
    3528             :                   int16 partnatts,
    3529             :                   AttrNumber *partattrs,
    3530             :                   List *partexprs,
    3531             :                   Oid *partopclass,
    3532             :                   Oid *partcollation)
    3533             : {
    3534             :     int         i;
    3535             :     int2vector *partattrs_vec;
    3536             :     oidvector  *partopclass_vec;
    3537             :     oidvector  *partcollation_vec;
    3538             :     Datum       partexprDatum;
    3539             :     Relation    pg_partitioned_table;
    3540             :     HeapTuple   tuple;
    3541             :     Datum       values[Natts_pg_partitioned_table];
    3542             :     bool        nulls[Natts_pg_partitioned_table];
    3543             :     ObjectAddress myself;
    3544             :     ObjectAddress referenced;
    3545             : 
    3546             :     Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
    3547             : 
    3548             :     /* Copy the partition attribute numbers, opclass OIDs into arrays */
    3549        2336 :     partattrs_vec = buildint2vector(partattrs, partnatts);
    3550        2336 :     partopclass_vec = buildoidvector(partopclass, partnatts);
    3551        2336 :     partcollation_vec = buildoidvector(partcollation, partnatts);
    3552             : 
    3553             :     /* Convert the expressions (if any) to a text datum */
    3554        2336 :     if (partexprs)
    3555             :     {
    3556             :         char       *exprString;
    3557             : 
    3558         140 :         exprString = nodeToString(partexprs);
    3559         140 :         partexprDatum = CStringGetTextDatum(exprString);
    3560         140 :         pfree(exprString);
    3561             :     }
    3562             :     else
    3563        2196 :         partexprDatum = (Datum) 0;
    3564             : 
    3565        2336 :     pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
    3566             : 
    3567        4672 :     MemSet(nulls, false, sizeof(nulls));
    3568             : 
    3569             :     /* Only this can ever be NULL */
    3570        2336 :     if (!partexprDatum)
    3571        2196 :         nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
    3572             : 
    3573        2336 :     values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
    3574        2336 :     values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
    3575        2336 :     values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
    3576        2336 :     values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
    3577        2336 :     values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
    3578        2336 :     values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
    3579        2336 :     values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
    3580        2336 :     values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
    3581             : 
    3582        2336 :     tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
    3583             : 
    3584        2336 :     CatalogTupleInsert(pg_partitioned_table, tuple);
    3585        2336 :     table_close(pg_partitioned_table, RowExclusiveLock);
    3586             : 
    3587             :     /* Mark this relation as dependent on a few things as follows */
    3588        2336 :     myself.classId = RelationRelationId;
    3589        2336 :     myself.objectId = RelationGetRelid(rel);
    3590        2336 :     myself.objectSubId = 0;
    3591             : 
    3592             :     /* Operator class and collation per key column */
    3593        4888 :     for (i = 0; i < partnatts; i++)
    3594             :     {
    3595        2552 :         referenced.classId = OperatorClassRelationId;
    3596        2552 :         referenced.objectId = partopclass[i];
    3597        2552 :         referenced.objectSubId = 0;
    3598             : 
    3599        2552 :         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
    3600             : 
    3601             :         /* The default collation is pinned, so don't bother recording it */
    3602        2552 :         if (OidIsValid(partcollation[i]) &&
    3603         332 :             partcollation[i] != DEFAULT_COLLATION_OID)
    3604             :         {
    3605          24 :             referenced.classId = CollationRelationId;
    3606          24 :             referenced.objectId = partcollation[i];
    3607          24 :             referenced.objectSubId = 0;
    3608             : 
    3609          24 :             recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
    3610             :         }
    3611             :     }
    3612             : 
    3613             :     /*
    3614             :      * The partitioning columns are made internally dependent on the table,
    3615             :      * because we cannot drop any of them without dropping the whole table.
    3616             :      * (ATExecDropColumn independently enforces that, but it's not bulletproof
    3617             :      * so we need the dependencies too.)
    3618             :      */
    3619        4888 :     for (i = 0; i < partnatts; i++)
    3620             :     {
    3621        2552 :         if (partattrs[i] == 0)
    3622         152 :             continue;           /* ignore expressions here */
    3623             : 
    3624        2400 :         referenced.classId = RelationRelationId;
    3625        2400 :         referenced.objectId = RelationGetRelid(rel);
    3626        2400 :         referenced.objectSubId = partattrs[i];
    3627             : 
    3628        2400 :         recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
    3629             :     }
    3630             : 
    3631             :     /*
    3632             :      * Also consider anything mentioned in partition expressions.  External
    3633             :      * references (e.g. functions) get NORMAL dependencies.  Table columns
    3634             :      * mentioned in the expressions are handled the same as plain partitioning
    3635             :      * columns, i.e. they become internally dependent on the whole table.
    3636             :      */
    3637        2336 :     if (partexprs)
    3638         140 :         recordDependencyOnSingleRelExpr(&myself,
    3639             :                                         (Node *) partexprs,
    3640             :                                         RelationGetRelid(rel),
    3641             :                                         DEPENDENCY_NORMAL,
    3642             :                                         DEPENDENCY_INTERNAL,
    3643             :                                         true /* reverse the self-deps */ );
    3644             : 
    3645             :     /*
    3646             :      * We must invalidate the relcache so that the next
    3647             :      * CommandCounterIncrement() will cause the same to be rebuilt using the
    3648             :      * information in just created catalog entry.
    3649             :      */
    3650        2336 :     CacheInvalidateRelcache(rel);
    3651        2336 : }
    3652             : 
    3653             : /*
    3654             :  *  RemovePartitionKeyByRelId
    3655             :  *      Remove pg_partitioned_table entry for a relation
    3656             :  */
    3657             : void
    3658        1828 : RemovePartitionKeyByRelId(Oid relid)
    3659             : {
    3660             :     Relation    rel;
    3661             :     HeapTuple   tuple;
    3662             : 
    3663        1828 :     rel = table_open(PartitionedRelationId, RowExclusiveLock);
    3664             : 
    3665        1828 :     tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
    3666        1828 :     if (!HeapTupleIsValid(tuple))
    3667           0 :         elog(ERROR, "cache lookup failed for partition key of relation %u",
    3668             :              relid);
    3669             : 
    3670        1828 :     CatalogTupleDelete(rel, &tuple->t_self);
    3671             : 
    3672        1828 :     ReleaseSysCache(tuple);
    3673        1828 :     table_close(rel, RowExclusiveLock);
    3674        1828 : }
    3675             : 
    3676             : /*
    3677             :  * StorePartitionBound
    3678             :  *      Update pg_class tuple of rel to store the partition bound and set
    3679             :  *      relispartition to true
    3680             :  *
    3681             :  * If this is the default partition, also update the default partition OID in
    3682             :  * pg_partitioned_table.
    3683             :  *
    3684             :  * Also, invalidate the parent's relcache, so that the next rebuild will load
    3685             :  * the new partition's info into its partition descriptor.  If there is a
    3686             :  * default partition, we must invalidate its relcache entry as well.
    3687             :  */
    3688             : void
    3689        4896 : StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound)
    3690             : {
    3691             :     Relation    classRel;
    3692             :     HeapTuple   tuple,
    3693             :                 newtuple;
    3694             :     Datum       new_val[Natts_pg_class];
    3695             :     bool        new_null[Natts_pg_class],
    3696             :                 new_repl[Natts_pg_class];
    3697             :     Oid         defaultPartOid;
    3698             : 
    3699             :     /* Update pg_class tuple */
    3700        4896 :     classRel = table_open(RelationRelationId, RowExclusiveLock);
    3701        4896 :     tuple = SearchSysCacheCopy1(RELOID,
    3702             :                                 ObjectIdGetDatum(RelationGetRelid(rel)));
    3703        4896 :     if (!HeapTupleIsValid(tuple))
    3704           0 :         elog(ERROR, "cache lookup failed for relation %u",
    3705             :              RelationGetRelid(rel));
    3706             : 
    3707             : #ifdef USE_ASSERT_CHECKING
    3708             :     {
    3709             :         Form_pg_class classForm;
    3710             :         bool        isnull;
    3711             : 
    3712             :         classForm = (Form_pg_class) GETSTRUCT(tuple);
    3713             :         Assert(!classForm->relispartition);
    3714             :         (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
    3715             :                                &isnull);
    3716             :         Assert(isnull);
    3717             :     }
    3718             : #endif
    3719             : 
    3720             :     /* Fill in relpartbound value */
    3721        4896 :     memset(new_val, 0, sizeof(new_val));
    3722        4896 :     memset(new_null, false, sizeof(new_null));
    3723        4896 :     memset(new_repl, false, sizeof(new_repl));
    3724        4896 :     new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
    3725        4896 :     new_null[Anum_pg_class_relpartbound - 1] = false;
    3726        4896 :     new_repl[Anum_pg_class_relpartbound - 1] = true;
    3727        4896 :     newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
    3728             :                                  new_val, new_null, new_repl);
    3729             :     /* Also set the flag */
    3730        4896 :     ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
    3731        4896 :     CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
    3732        4896 :     heap_freetuple(newtuple);
    3733        4896 :     table_close(classRel, RowExclusiveLock);
    3734             : 
    3735             :     /*
    3736             :      * If we're storing bounds for the default partition, update
    3737             :      * pg_partitioned_table too.
    3738             :      */
    3739        4896 :     if (bound->is_default)
    3740         278 :         update_default_partition_oid(RelationGetRelid(parent),
    3741             :                                      RelationGetRelid(rel));
    3742             : 
    3743             :     /* Make these updates visible */
    3744        4896 :     CommandCounterIncrement();
    3745             : 
    3746             :     /*
    3747             :      * The partition constraint for the default partition depends on the
    3748             :      * partition bounds of every other partition, so we must invalidate the
    3749             :      * relcache entry for that partition every time a partition is added or
    3750             :      * removed.
    3751             :      */
    3752        4896 :     defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
    3753        4896 :     if (OidIsValid(defaultPartOid))
    3754         380 :         CacheInvalidateRelcacheByRelid(defaultPartOid);
    3755             : 
    3756        4896 :     CacheInvalidateRelcache(parent);
    3757        4896 : }

Generated by: LCOV version 1.13