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

Generated by: LCOV version 1.13