PostgreSQL Source Code git master
Loading...
Searching...
No Matches
heap.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/multixact.h"
#include "access/relation.h"
#include "access/table.h"
#include "access/tableam.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/objectaccess.h"
#include "catalog/partition.h"
#include "catalog/pg_am.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_foreign_table.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_subscription_rel.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/storage.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
#include "common/int.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "parser/parsetree.h"
#include "partitioning/partdesc.h"
#include "pgstat.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Include dependency graph for heap.c:

Go to the source code of this file.

Functions

static void AddNewRelationTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Oid reloftype, Oid relowner, char relkind, TransactionId relfrozenxid, TransactionId relminmxid, Datum relacl, Datum reloptions)
 
static ObjectAddress AddNewRelationType (const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type)
 
static void RelationRemoveInheritance (Oid relid)
 
static Oid StoreRelCheck (Relation rel, const char *ccname, Node *expr, bool is_enforced, bool is_validated, bool is_local, int16 inhcount, bool is_no_inherit, bool is_internal)
 
static void StoreConstraints (Relation rel, List *cooked_constraints, bool is_internal)
 
static bool MergeWithExistingConstraint (Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_enforced, bool is_initially_valid, bool is_no_inherit)
 
static void SetRelationNumChecks (Relation rel, int numchecks)
 
static NodecookConstraint (ParseState *pstate, Node *raw_constraint, char *relname)
 
const FormData_pg_attributeSystemAttributeDefinition (AttrNumber attno)
 
const FormData_pg_attributeSystemAttributeByName (const char *attname)
 
Relation heap_create (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, RelFileNumber relfilenumber, Oid accessmtd, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods, TransactionId *relfrozenxid, MultiXactId *relminmxid, bool create_storage)
 
void CheckAttributeNamesTypes (TupleDesc tupdesc, char relkind, int flags)
 
void CheckAttributeType (const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
 
void InsertPgAttributeTuples (Relation pg_attribute_rel, TupleDesc tupdesc, Oid new_rel_oid, const FormExtraData_pg_attribute tupdesc_extra[], CatalogIndexState indstate)
 
static void AddNewAttributeTuples (Oid new_rel_oid, TupleDesc tupdesc, char relkind)
 
void InsertPgClassTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
 
Oid heap_create_with_catalog (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid reltypeid, Oid reloftypeid, Oid ownerid, Oid accessmtd, TupleDesc tupdesc, List *cooked_constraints, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, OnCommitAction oncommit, Datum reloptions, bool use_user_acl, bool allow_system_table_mods, bool is_internal, Oid relrewrite, ObjectAddress *typaddress)
 
void DeleteRelationTuple (Oid relid)
 
void DeleteAttributeTuples (Oid relid)
 
void DeleteSystemAttributeTuples (Oid relid)
 
void RemoveAttributeById (Oid relid, AttrNumber attnum)
 
void heap_drop_with_catalog (Oid relid)
 
void RelationClearMissing (Relation rel)
 
void StoreAttrMissingVal (Relation rel, AttrNumber attnum, Datum missingval)
 
void SetAttrMissing (Oid relid, char *attname, char *value)
 
static Oid StoreRelNotNull (Relation rel, const char *nnname, AttrNumber attnum, bool is_validated, bool is_local, int inhcount, bool is_no_inherit)
 
ListAddRelationNewConstraints (Relation rel, List *newColDefaults, List *newConstraints, bool allow_merge, bool is_local, bool is_internal, const char *queryString)
 
ListAddRelationNotNullConstraints (Relation rel, List *constraints, List *old_notnulls, List *existing_constraints)
 
static bool check_nested_generated_walker (Node *node, void *context)
 
static void check_nested_generated (ParseState *pstate, Node *node)
 
static bool contains_user_functions_checker (Oid func_id, void *context)
 
static bool check_virtual_generated_security_walker (Node *node, void *context)
 
static void check_virtual_generated_security (ParseState *pstate, Node *node)
 
NodecookDefault (ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
 
void CopyStatistics (Oid fromrelid, Oid torelid)
 
void RemoveStatistics (Oid relid, AttrNumber attnum)
 
static void RelationTruncateIndexes (Relation heapRelation)
 
void heap_truncate (List *relids)
 
void heap_truncate_one_rel (Relation rel)
 
void heap_truncate_check_FKs (List *relations, bool tempTables)
 
Listheap_truncate_find_FKs (List *relationIds)
 
void StorePartitionKey (Relation rel, char strategy, int16 partnatts, AttrNumber *partattrs, List *partexprs, Oid *partopclass, Oid *partcollation)
 
void RemovePartitionKeyByRelId (Oid relid)
 
void StorePartitionBound (Relation rel, Relation parent, PartitionBoundSpec *bound)
 

Variables

Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid
 
Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid
 
RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber = InvalidRelFileNumber
 
RelFileNumber binary_upgrade_next_toast_pg_class_relfilenumber = InvalidRelFileNumber
 
static const FormData_pg_attribute a1
 
static const FormData_pg_attribute a2
 
static const FormData_pg_attribute a3
 
static const FormData_pg_attribute a4
 
static const FormData_pg_attribute a5
 
static const FormData_pg_attribute a6
 
static const FormData_pg_attribute *const SysAtt [] = {&a1, &a2, &a3, &a4, &a5, &a6}
 

Function Documentation

◆ AddNewAttributeTuples()

static void AddNewAttributeTuples ( Oid  new_rel_oid,
TupleDesc  tupdesc,
char  relkind 
)
static

Definition at line 848 of file heap.c.

851{
852 Relation rel;
854 int natts = tupdesc->natts;
857
858 /*
859 * open pg_attribute and its indexes.
860 */
862
864
866
867 /* add dependencies on their datatypes and collations */
868 for (int i = 0; i < natts; i++)
869 {
870 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
871
872 /* Add dependency info */
876
877 /* The default collation is pinned, so don't bother recording it */
878 if (OidIsValid(attr->attcollation) &&
879 attr->attcollation != DEFAULT_COLLATION_OID)
880 {
882 attr->attcollation);
884 }
885 }
886
887 /*
888 * Next we add the system attributes. Skip all for a view or type
889 * relation. We don't bother with making datatype dependencies here,
890 * since presumably all these types are pinned.
891 */
892 if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
893 {
894 TupleDesc td;
895
897
899 FreeTupleDesc(td);
900 }
901
902 /*
903 * clean up
904 */
906
908}
#define lengthof(array)
Definition c.h:873
#define OidIsValid(objectId)
Definition c.h:858
@ DEPENDENCY_NORMAL
Definition dependency.h:33
static const FormData_pg_attribute *const SysAtt[]
Definition heap.c:228
void InsertPgAttributeTuples(Relation pg_attribute_rel, TupleDesc tupdesc, Oid new_rel_oid, const FormExtraData_pg_attribute tupdesc_extra[], CatalogIndexState indstate)
Definition heap.c:731
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition indexing.c:61
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition indexing.c:43
int i
Definition isn.c:77
#define RowExclusiveLock
Definition lockdefs.h:38
#define ObjectAddressSet(addr, class_id, object_id)
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
FormData_pg_attribute
FormData_pg_attribute * Form_pg_attribute
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
static int fb(int x)
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
void FreeTupleDesc(TupleDesc tupdesc)
Definition tupdesc.c:560
TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs)
Definition tupdesc.c:216
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

References CatalogCloseIndexes(), CatalogOpenIndexes(), CreateTupleDesc(), DEPENDENCY_NORMAL, fb(), FormData_pg_attribute, FreeTupleDesc(), i, InsertPgAttributeTuples(), lengthof, TupleDescData::natts, ObjectAddressSet, ObjectAddressSubSet, OidIsValid, recordDependencyOn(), RowExclusiveLock, SysAtt, table_close(), table_open(), and TupleDescAttr().

Referenced by heap_create_with_catalog().

◆ AddNewRelationTuple()

static void AddNewRelationTuple ( Relation  pg_class_desc,
Relation  new_rel_desc,
Oid  new_rel_oid,
Oid  new_type_oid,
Oid  reloftype,
Oid  relowner,
char  relkind,
TransactionId  relfrozenxid,
TransactionId  relminmxid,
Datum  relacl,
Datum  reloptions 
)
static

Definition at line 998 of file heap.c.

1009{
1011
1012 /*
1013 * first we update some of the information in our uncataloged relation's
1014 * relation descriptor.
1015 */
1016 new_rel_reltup = new_rel_desc->rd_rel;
1017
1018 /* The relation is empty */
1019 new_rel_reltup->relpages = 0;
1020 new_rel_reltup->reltuples = -1;
1021 new_rel_reltup->relallvisible = 0;
1022 new_rel_reltup->relallfrozen = 0;
1023
1024 /* Sequences always have a known size */
1025 if (relkind == RELKIND_SEQUENCE)
1026 {
1027 new_rel_reltup->relpages = 1;
1028 new_rel_reltup->reltuples = 1;
1029 }
1030
1031 new_rel_reltup->relfrozenxid = relfrozenxid;
1032 new_rel_reltup->relminmxid = relminmxid;
1033 new_rel_reltup->relowner = relowner;
1034 new_rel_reltup->reltype = new_type_oid;
1035 new_rel_reltup->reloftype = reloftype;
1036
1037 /* relispartition is always set by updating this tuple later */
1038 new_rel_reltup->relispartition = false;
1039
1040 /* fill rd_att's type ID with something sane even if reltype is zero */
1041 new_rel_desc->rd_att->tdtypeid = new_type_oid ? new_type_oid : RECORDOID;
1042 new_rel_desc->rd_att->tdtypmod = -1;
1043
1044 /* Now build and insert the tuple */
1046 relacl, reloptions);
1047}
void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
Definition heap.c:924
FormData_pg_class * Form_pg_class
Definition pg_class.h:160

References fb(), and InsertPgClassTuple().

Referenced by heap_create_with_catalog().

◆ AddNewRelationType()

static ObjectAddress AddNewRelationType ( const char typeName,
Oid  typeNamespace,
Oid  new_rel_oid,
char  new_rel_kind,
Oid  ownerid,
Oid  new_row_type,
Oid  new_array_type 
)
static

Definition at line 1057 of file heap.c.

1064{
1065 return
1066 TypeCreate(new_row_type, /* optional predetermined OID */
1067 typeName, /* type name */
1068 typeNamespace, /* type namespace */
1069 new_rel_oid, /* relation oid */
1070 new_rel_kind, /* relation kind */
1071 ownerid, /* owner's ID */
1072 -1, /* internal size (varlena) */
1073 TYPTYPE_COMPOSITE, /* type-type (composite) */
1074 TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
1075 false, /* composite types are never preferred */
1076 DEFAULT_TYPDELIM, /* default array delimiter */
1077 F_RECORD_IN, /* input procedure */
1078 F_RECORD_OUT, /* output procedure */
1079 F_RECORD_RECV, /* receive procedure */
1080 F_RECORD_SEND, /* send procedure */
1081 InvalidOid, /* typmodin procedure - none */
1082 InvalidOid, /* typmodout procedure - none */
1083 InvalidOid, /* analyze procedure - default */
1084 InvalidOid, /* subscript procedure - none */
1085 InvalidOid, /* array element type - irrelevant */
1086 false, /* this is not an array type */
1087 new_array_type, /* array type if any */
1088 InvalidOid, /* domain base type - irrelevant */
1089 NULL, /* default value - none */
1090 NULL, /* default binary representation */
1091 false, /* passed by reference */
1092 TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1093 TYPSTORAGE_EXTENDED, /* fully TOASTable */
1094 -1, /* typmod */
1095 0, /* array dimensions for typBaseType */
1096 false, /* Type NOT NULL */
1097 InvalidOid); /* rowtypes never have a collation */
1098}
ObjectAddress TypeCreate(Oid newTypeOid, const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, Oid ownerId, int16 internalSize, char typeType, char typeCategory, bool typePreferred, char typDelim, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid subscriptProcedure, Oid elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation)
Definition pg_type.c:195
#define InvalidOid
#define DEFAULT_TYPDELIM
Definition typecmds.h:22

References DEFAULT_TYPDELIM, fb(), InvalidOid, and TypeCreate().

Referenced by heap_create_with_catalog().

◆ AddRelationNewConstraints()

List * AddRelationNewConstraints ( Relation  rel,
List newColDefaults,
List newConstraints,
bool  allow_merge,
bool  is_local,
bool  is_internal,
const char queryString 
)

Definition at line 2399 of file heap.c.

2406{
2410 int numoldchecks;
2411 ParseState *pstate;
2413 int numchecks;
2415 List *nnnames;
2416 Node *expr;
2418
2419 /*
2420 * Get info about existing constraints.
2421 */
2423 oldconstr = tupleDesc->constr;
2424 if (oldconstr)
2425 numoldchecks = oldconstr->num_check;
2426 else
2427 numoldchecks = 0;
2428
2429 /*
2430 * Create a dummy ParseState and insert the target relation as its sole
2431 * rangetable entry. We need a ParseState for transformExpr.
2432 */
2433 pstate = make_parsestate(NULL);
2434 pstate->p_sourcetext = queryString;
2436 rel,
2438 NULL,
2439 false,
2440 true);
2441 addNSItemToQuery(pstate, nsitem, true, true, true);
2442
2443 /*
2444 * Process column default expressions.
2445 */
2447 {
2448 Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2449 Oid defOid;
2450
2451 expr = cookDefault(pstate, colDef->raw_default,
2452 atp->atttypid, atp->atttypmod,
2453 NameStr(atp->attname),
2454 atp->attgenerated);
2455
2456 /*
2457 * If the expression is just a NULL constant, we do not bother to make
2458 * an explicit pg_attrdef entry, since the default behavior is
2459 * equivalent. This applies to column defaults, but not for
2460 * generation expressions.
2461 *
2462 * Note a nonobvious property of this test: if the column is of a
2463 * domain type, what we'll get is not a bare null Const but a
2464 * CoerceToDomain expr, so we will not discard the default. This is
2465 * critical because the column default needs to be retained to
2466 * override any default that the domain might have.
2467 */
2468 if (expr == NULL ||
2469 (!colDef->generated &&
2470 IsA(expr, Const) &&
2471 castNode(Const, expr)->constisnull))
2472 continue;
2473
2474 defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
2475
2477 cooked->contype = CONSTR_DEFAULT;
2478 cooked->conoid = defOid;
2479 cooked->name = NULL;
2480 cooked->attnum = colDef->attnum;
2481 cooked->expr = expr;
2482 cooked->is_enforced = true;
2483 cooked->skip_validation = false;
2484 cooked->is_local = is_local;
2485 cooked->inhcount = is_local ? 0 : 1;
2486 cooked->is_no_inherit = false;
2488 }
2489
2490 /*
2491 * Process constraint expressions.
2492 */
2494 checknames = NIL;
2495 nnnames = NIL;
2497 {
2498 Oid constrOid;
2499
2500 if (cdef->contype == CONSTR_CHECK)
2501 {
2502 char *ccname;
2503
2504 if (cdef->raw_expr != NULL)
2505 {
2506 Assert(cdef->cooked_expr == NULL);
2507
2508 /*
2509 * Transform raw parsetree to executable expression, and
2510 * verify it's valid as a CHECK constraint.
2511 */
2512 expr = cookConstraint(pstate, cdef->raw_expr,
2514 }
2515 else
2516 {
2517 Assert(cdef->cooked_expr != NULL);
2518
2519 /*
2520 * Here, we assume the parser will only pass us valid CHECK
2521 * expressions, so we do no particular checking.
2522 */
2523 expr = stringToNode(cdef->cooked_expr);
2524 }
2525
2526 /*
2527 * Check name uniqueness, or generate a name if none was given.
2528 */
2529 if (cdef->conname != NULL)
2530 {
2531 ccname = cdef->conname;
2532 /* Check against other new constraints */
2533 /* Needed because we don't do CommandCounterIncrement in loop */
2535 {
2536 if (strcmp(chkname, ccname) == 0)
2537 ereport(ERROR,
2539 errmsg("check constraint \"%s\" already exists",
2540 ccname)));
2541 }
2542
2543 /* save name for future checks */
2544 checknames = lappend(checknames, ccname);
2545
2546 /*
2547 * Check against pre-existing constraints. If we are allowed
2548 * to merge with an existing constraint, there's no more to do
2549 * here. (We omit the duplicate constraint from the result,
2550 * which is what ATAddCheckNNConstraint wants.)
2551 */
2552 if (MergeWithExistingConstraint(rel, ccname, expr,
2553 allow_merge, is_local,
2554 cdef->is_enforced,
2555 cdef->initially_valid,
2556 cdef->is_no_inherit))
2557 continue;
2558 }
2559 else
2560 {
2561 /*
2562 * When generating a name, we want to create "tab_col_check"
2563 * for a column constraint and "tab_check" for a table
2564 * constraint. We no longer have any info about the syntactic
2565 * positioning of the constraint phrase, so we approximate
2566 * this by seeing whether the expression references more than
2567 * one column. (If the user played by the rules, the result
2568 * is the same...)
2569 *
2570 * Note: pull_var_clause() doesn't descend into sublinks, but
2571 * we eliminated those above; and anyway this only needs to be
2572 * an approximate answer.
2573 */
2574 List *vars;
2575 char *colname;
2576
2577 vars = pull_var_clause(expr, 0);
2578
2579 /* eliminate duplicates */
2580 vars = list_union(NIL, vars);
2581
2582 if (list_length(vars) == 1)
2583 colname = get_attname(RelationGetRelid(rel),
2584 ((Var *) linitial(vars))->varattno,
2585 true);
2586 else
2587 colname = NULL;
2588
2590 colname,
2591 "check",
2593 checknames);
2594
2595 /* save name for future checks */
2596 checknames = lappend(checknames, ccname);
2597 }
2598
2599 /*
2600 * OK, store it.
2601 */
2602 constrOid =
2603 StoreRelCheck(rel, ccname, expr, cdef->is_enforced,
2604 cdef->initially_valid, is_local,
2605 is_local ? 0 : 1, cdef->is_no_inherit,
2606 is_internal);
2607
2608 numchecks++;
2609
2611 cooked->contype = CONSTR_CHECK;
2612 cooked->conoid = constrOid;
2613 cooked->name = ccname;
2614 cooked->attnum = 0;
2615 cooked->expr = expr;
2616 cooked->is_enforced = cdef->is_enforced;
2617 cooked->skip_validation = cdef->skip_validation;
2618 cooked->is_local = is_local;
2619 cooked->inhcount = is_local ? 0 : 1;
2620 cooked->is_no_inherit = cdef->is_no_inherit;
2622 }
2623 else if (cdef->contype == CONSTR_NOTNULL)
2624 {
2626 AttrNumber colnum;
2627 int16 inhcount = is_local ? 0 : 1;
2628 char *nnname;
2629
2630 /* Determine which column to modify */
2631 colnum = get_attnum(RelationGetRelid(rel), strVal(linitial(cdef->keys)));
2632 if (colnum == InvalidAttrNumber)
2633 ereport(ERROR,
2635 errmsg("column \"%s\" of relation \"%s\" does not exist",
2637 if (colnum < InvalidAttrNumber)
2638 ereport(ERROR,
2640 errmsg("cannot add not-null constraint on system column \"%s\"",
2641 strVal(linitial(cdef->keys))));
2642
2643 Assert(cdef->initially_valid != cdef->skip_validation);
2644
2645 /*
2646 * If the column already has a not-null constraint, we don't want
2647 * to add another one; adjust inheritance status as needed. This
2648 * also checks whether the existing constraint matches the
2649 * requested validity.
2650 */
2652 cdef->conname,
2653 is_local, cdef->is_no_inherit,
2654 cdef->skip_validation))
2655 continue;
2656
2657 /*
2658 * If a constraint name is specified, check that it isn't already
2659 * used. Otherwise, choose a non-conflicting one ourselves.
2660 */
2661 if (cdef->conname)
2662 {
2664 RelationGetRelid(rel),
2665 cdef->conname))
2666 ereport(ERROR,
2668 errmsg("constraint \"%s\" for relation \"%s\" already exists",
2669 cdef->conname, RelationGetRelationName(rel)));
2670 nnname = cdef->conname;
2671 }
2672 else
2674 strVal(linitial(cdef->keys)),
2675 "not_null",
2677 nnnames);
2679
2680 constrOid =
2681 StoreRelNotNull(rel, nnname, colnum,
2682 cdef->initially_valid,
2683 is_local,
2684 inhcount,
2685 cdef->is_no_inherit);
2686
2688 nncooked->contype = CONSTR_NOTNULL;
2689 nncooked->conoid = constrOid;
2690 nncooked->name = nnname;
2691 nncooked->attnum = colnum;
2692 nncooked->expr = NULL;
2693 nncooked->is_enforced = true;
2694 nncooked->skip_validation = cdef->skip_validation;
2695 nncooked->is_local = is_local;
2696 nncooked->inhcount = inhcount;
2697 nncooked->is_no_inherit = cdef->is_no_inherit;
2698
2700 }
2701 }
2702
2703 /*
2704 * Update the count of constraints in the relation's pg_class tuple. We do
2705 * this even if there was no change, in order to ensure that an SI update
2706 * message is sent out for the pg_class tuple, which will force other
2707 * backends to rebuild their relcache entries for the rel. (This is
2708 * critical if we added defaults but not constraints.)
2709 */
2711
2712 return cookedConstraints;
2713}
int16 AttrNumber
Definition attnum.h:21
#define InvalidAttrNumber
Definition attnum.h:23
#define NameStr(name)
Definition c.h:835
#define Assert(condition)
Definition c.h:943
int16_t int16
Definition c.h:619
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
#define palloc_object(type)
Definition fe_memutils.h:74
static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr, bool is_enforced, bool is_validated, bool is_local, int16 inhcount, bool is_no_inherit, bool is_internal)
Definition heap.c:2161
static bool MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_enforced, bool is_initially_valid, bool is_no_inherit)
Definition heap.c:2726
static Oid StoreRelNotNull(Relation rel, const char *nnname, AttrNumber attnum, bool is_validated, bool is_local, int inhcount, bool is_no_inherit)
Definition heap.c:2268
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition heap.c:3163
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
Definition heap.c:3337
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition heap.c:3418
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_union(const List *list1, const List *list2)
Definition list.c:1066
#define AccessShareLock
Definition lockdefs.h:36
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:977
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:946
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define castNode(_type_, nodeptr)
Definition nodes.h:182
static char * errmsg
ParseState * make_parsestate(ParseState *parentParseState)
Definition parse_node.c:39
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, LOCKMODE lockmode, Alias *alias, bool inh, bool inFromCl)
@ CONSTR_DEFAULT
@ CONSTR_NOTNULL
@ CONSTR_CHECK
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal)
Definition pg_attrdef.c:37
bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, const char *conname)
bool AdjustNotNullInheritance(Oid relid, AttrNumber attnum, const char *new_conname, bool is_local, bool is_no_inherit, bool is_notvalid)
char * ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
@ CONSTRAINT_RELATION
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
#define linitial(l)
Definition pg_list.h:178
#define foreach_node(type, var, lst)
Definition pg_list.h:528
unsigned int Oid
void * stringToNode(const char *str)
Definition read.c:90
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetDescr(relation)
Definition rel.h:542
#define RelationGetRelationName(relation)
Definition rel.h:550
#define RelationGetNamespace(relation)
Definition rel.h:557
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
Definition pg_list.h:54
Definition nodes.h:135
const char * p_sourcetext
Definition parse_node.h:214
TupleDesc rd_att
Definition rel.h:112
#define strVal(v)
Definition value.h:82
List * pull_var_clause(Node *node, int flags)
Definition var.c:653

References AccessShareLock, addNSItemToQuery(), addRangeTableEntryForRelation(), AdjustNotNullInheritance(), Assert, castNode, ChooseConstraintName(), CONSTR_CHECK, CONSTR_DEFAULT, CONSTR_NOTNULL, CONSTRAINT_RELATION, ConstraintNameIsUsed(), cookConstraint(), cookDefault(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg, ERROR, fb(), foreach_node, foreach_ptr, get_attname(), get_attnum(), InvalidAttrNumber, IsA, lappend(), linitial, list_length(), list_union(), make_parsestate(), MergeWithExistingConstraint(), NameStr, NIL, ParseState::p_sourcetext, palloc_object, pull_var_clause(), RelationData::rd_att, RelationGetDescr, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, SetRelationNumChecks(), StoreAttrDefault(), StoreRelCheck(), StoreRelNotNull(), stringToNode(), strVal, and TupleDescAttr().

Referenced by ATAddCheckNNConstraint(), ATExecAddColumn(), ATExecColumnDefault(), ATExecSetExpression(), ATExecSetNotNull(), createTableConstraints(), and DefineRelation().

◆ AddRelationNotNullConstraints()

List * AddRelationNotNullConstraints ( Relation  rel,
List constraints,
List old_notnulls,
List existing_constraints 
)

Definition at line 2911 of file heap.c.

2913{
2915 List *nnnames;
2916 List *nncols = NIL;
2917
2918 /*
2919 * We track two lists of names: nnnames keeps all the constraint names,
2920 * givennames tracks user-generated names. The distinction is important,
2921 * because we must raise error for user-generated name conflicts, but for
2922 * system-generated name conflicts we just generate another.
2923 */
2924 nnnames = list_copy(existing_constraints); /* don't scribble on input */
2925 givennames = NIL;
2926
2927 /*
2928 * First, create all not-null constraints that are directly specified by
2929 * the user. Note that inheritance might have given us another source for
2930 * each, so we must scan the old_notnulls list and increment inhcount for
2931 * each element with identical attnum. We delete from there any element
2932 * that we process.
2933 *
2934 * We don't use foreach() here because we have two nested loops over the
2935 * constraint list, with possible element deletions in the inner one. If
2936 * we used foreach_delete_current() it could only fix up the state of one
2937 * of the loops, so it seems cleaner to use looping over list indexes for
2938 * both loops. Note that any deletion will happen beyond where the outer
2939 * loop is, so its index never needs adjustment.
2940 */
2941 for (int outerpos = 0; outerpos < list_length(constraints); outerpos++)
2942 {
2943 Constraint *constr;
2945 char *conname;
2946 int inhcount = 0;
2947
2948 constr = list_nth_node(Constraint, constraints, outerpos);
2949
2950 Assert(constr->contype == CONSTR_NOTNULL);
2951
2953 strVal(linitial(constr->keys)));
2955 ereport(ERROR,
2957 errmsg("column \"%s\" of relation \"%s\" does not exist",
2958 strVal(linitial(constr->keys)),
2961 ereport(ERROR,
2963 errmsg("cannot add not-null constraint on system column \"%s\"",
2964 strVal(linitial(constr->keys))));
2965
2966 /*
2967 * A column can only have one not-null constraint, so discard any
2968 * additional ones that appear for columns we already saw; but check
2969 * that the NO INHERIT flags match.
2970 */
2971 for (int restpos = outerpos + 1; restpos < list_length(constraints);)
2972 {
2974
2975 other = list_nth_node(Constraint, constraints, restpos);
2976 if (strcmp(strVal(linitial(constr->keys)),
2977 strVal(linitial(other->keys))) == 0)
2978 {
2979 if (other->is_no_inherit != constr->is_no_inherit)
2980 ereport(ERROR,
2982 errmsg("conflicting NO INHERIT declaration for not-null constraint on column \"%s\"",
2983 strVal(linitial(constr->keys))));
2984
2985 /*
2986 * Preserve constraint name if one is specified, but raise an
2987 * error if conflicting ones are specified.
2988 */
2989 if (other->conname)
2990 {
2991 if (!constr->conname)
2992 constr->conname = pstrdup(other->conname);
2993 else if (strcmp(constr->conname, other->conname) != 0)
2994 ereport(ERROR,
2996 errmsg("conflicting not-null constraint names \"%s\" and \"%s\"",
2997 constr->conname, other->conname));
2998 }
2999
3000 /* XXX do we need to verify any other fields? */
3001 constraints = list_delete_nth_cell(constraints, restpos);
3002 }
3003 else
3004 restpos++;
3005 }
3006
3007 /*
3008 * Search in the list of inherited constraints for any entries on the
3009 * same column; determine an inheritance count from that. Also, if at
3010 * least one parent has a constraint for this column, then we must not
3011 * accept a user specification for a NO INHERIT one. Any constraint
3012 * from parents that we process here is deleted from the list: we no
3013 * longer need to process it in the loop below.
3014 */
3016 {
3017 if (old->attnum == attnum)
3018 {
3019 /*
3020 * If we get a constraint from the parent, having a local NO
3021 * INHERIT one doesn't work.
3022 */
3023 if (constr->is_no_inherit)
3024 ereport(ERROR,
3026 errmsg("cannot define not-null constraint with NO INHERIT on column \"%s\"",
3027 strVal(linitial(constr->keys))),
3028 errdetail("The column has an inherited not-null constraint.")));
3029
3030 inhcount++;
3032 }
3033 }
3034
3035 /*
3036 * Determine a constraint name, which may have been specified by the
3037 * user, or raise an error if a conflict exists with another
3038 * user-specified name.
3039 */
3040 if (constr->conname)
3041 {
3043 {
3044 if (strcmp(thisname, constr->conname) == 0)
3045 ereport(ERROR,
3047 errmsg("constraint \"%s\" for relation \"%s\" already exists",
3048 constr->conname,
3050 }
3051
3052 conname = constr->conname;
3053 givennames = lappend(givennames, conname);
3054 }
3055 else
3058 attnum, false),
3059 "not_null",
3061 nnnames);
3062 nnnames = lappend(nnnames, conname);
3063
3064 StoreRelNotNull(rel, conname,
3065 attnum, true, true,
3066 inhcount, constr->is_no_inherit);
3067
3069 }
3070
3071 /*
3072 * If any column remains in the old_notnulls list, we must create a not-
3073 * null constraint marked not-local for that column. Because multiple
3074 * parents could specify a not-null constraint for the same column, we
3075 * must count how many there are and set an appropriate inhcount
3076 * accordingly, deleting elements we've already processed.
3077 *
3078 * We don't use foreach() here because we have two nested loops over the
3079 * constraint list, with possible element deletions in the inner one. If
3080 * we used foreach_delete_current() it could only fix up the state of one
3081 * of the loops, so it seems cleaner to use looping over list indexes for
3082 * both loops. Note that any deletion will happen beyond where the outer
3083 * loop is, so its index never needs adjustment.
3084 */
3086 {
3088 char *conname = NULL;
3089 int inhcount = 1;
3090
3092 Assert(cooked->contype == CONSTR_NOTNULL);
3093 Assert(cooked->name);
3094
3095 /*
3096 * Preserve the first non-conflicting constraint name we come across.
3097 */
3098 if (conname == NULL)
3099 conname = cooked->name;
3100
3101 for (int restpos = outerpos + 1; restpos < list_length(old_notnulls);)
3102 {
3104
3106 Assert(other->name);
3107 if (other->attnum == cooked->attnum)
3108 {
3109 if (conname == NULL)
3110 conname = other->name;
3111
3112 inhcount++;
3114 }
3115 else
3116 restpos++;
3117 }
3118
3119 /* If we got a name, make sure it isn't one we've already used */
3120 if (conname != NULL)
3121 {
3123 {
3124 if (strcmp(thisname, conname) == 0)
3125 {
3126 conname = NULL;
3127 break;
3128 }
3129 }
3130 }
3131
3132 /* and choose a name, if needed */
3133 if (conname == NULL)
3136 cooked->attnum, false),
3137 "not_null",
3139 nnnames);
3140 nnnames = lappend(nnnames, conname);
3141
3142 /* ignore the origin constraint's is_local and inhcount */
3143 StoreRelNotNull(rel, conname, cooked->attnum, true,
3144 false, inhcount, false);
3145
3146 nncols = lappend_int(nncols, cooked->attnum);
3147 }
3148
3149 return nncols;
3150}
int errdetail(const char *fmt,...) pg_attribute_printf(1
List * list_delete_nth_cell(List *list, int n)
Definition list.c:767
List * list_copy(const List *oldlist)
Definition list.c:1573
List * lappend_int(List *list, int datum)
Definition list.c:357
char * pstrdup(const char *in)
Definition mcxt.c:1781
int16 attnum
#define foreach_delete_current(lst, var_or_cell)
Definition pg_list.h:423
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
#define list_nth_node(type, list, n)
Definition pg_list.h:359
List * keys
ConstrType contype
bool is_no_inherit
char * conname

References Assert, attnum, ChooseConstraintName(), Constraint::conname, CONSTR_NOTNULL, Constraint::contype, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg, ERROR, fb(), foreach_delete_current, foreach_ptr, get_attname(), get_attnum(), InvalidAttrNumber, Constraint::is_no_inherit, Constraint::keys, lappend(), lappend_int(), linitial, list_copy(), list_delete_nth_cell(), list_length(), list_nth(), list_nth_node, NIL, pstrdup(), RelationGetNamespace, RelationGetRelationName, RelationGetRelid, StoreRelNotNull(), and strVal.

Referenced by DefineRelation().

◆ check_nested_generated()

static void check_nested_generated ( ParseState pstate,
Node node 
)
static

Definition at line 3239 of file heap.c.

3240{
3241 check_nested_generated_walker(node, pstate);
3242}
static bool check_nested_generated_walker(Node *node, void *context)
Definition heap.c:3197

References check_nested_generated_walker().

Referenced by cookDefault().

◆ check_nested_generated_walker()

static bool check_nested_generated_walker ( Node node,
void context 
)
static

Definition at line 3197 of file heap.c.

3198{
3199 ParseState *pstate = context;
3200
3201 if (node == NULL)
3202 return false;
3203 else if (IsA(node, Var))
3204 {
3205 Var *var = (Var *) node;
3206 Oid relid;
3208
3209 relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
3210 if (!OidIsValid(relid))
3211 return false; /* XXX shouldn't we raise an error? */
3212
3213 attnum = var->varattno;
3214
3215 if (attnum > 0 && get_attgenerated(relid, attnum))
3216 ereport(ERROR,
3218 errmsg("cannot use generated column \"%s\" in column generation expression",
3219 get_attname(relid, attnum, false)),
3220 errdetail("A generated column cannot reference another generated column."),
3221 parser_errposition(pstate, var->location)));
3222 /* A whole-row Var is necessarily self-referential, so forbid it */
3223 if (attnum == 0)
3224 ereport(ERROR,
3226 errmsg("cannot use whole-row variable in column generation expression"),
3227 errdetail("This would cause the generated column to depend on its own value."),
3228 parser_errposition(pstate, var->location)));
3229 /* System columns were already checked in the parser */
3230
3231 return false;
3232 }
3233 else
3235 context);
3236}
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1007
#define expression_tree_walker(n, w, c)
Definition nodeFuncs.h:153
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
#define rt_fetch(rangetable_index, rangetable)
Definition parsetree.h:31
List * p_rtable
Definition parse_node.h:215
ParseLoc location
Definition primnodes.h:311
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270

References attnum, check_nested_generated_walker(), ereport, errcode(), errdetail(), errmsg, ERROR, expression_tree_walker, fb(), get_attgenerated(), get_attname(), IsA, Var::location, OidIsValid, ParseState::p_rtable, parser_errposition(), rt_fetch, Var::varattno, and Var::varno.

Referenced by check_nested_generated(), and check_nested_generated_walker().

◆ check_virtual_generated_security()

static void check_virtual_generated_security ( ParseState pstate,
Node node 
)
static

Definition at line 3319 of file heap.c.

3320{
3322}
static bool check_virtual_generated_security_walker(Node *node, void *context)
Definition heap.c:3282

References check_virtual_generated_security_walker().

Referenced by cookDefault().

◆ check_virtual_generated_security_walker()

static bool check_virtual_generated_security_walker ( Node node,
void context 
)
static

Definition at line 3282 of file heap.c.

3283{
3284 ParseState *pstate = context;
3285
3286 if (node == NULL)
3287 return false;
3288
3289 if (!IsA(node, List))
3290 {
3292 ereport(ERROR,
3294 errmsg("generation expression uses user-defined function"),
3295 errdetail("Virtual generated columns that make use of user-defined functions are not yet supported."),
3296 parser_errposition(pstate, exprLocation(node)));
3297
3298 /*
3299 * check_functions_in_node() doesn't check some node types (see
3300 * comment there). We handle CoerceToDomain and MinMaxExpr by
3301 * checking for built-in types. The other listed node types cannot
3302 * call user-definable SQL-visible functions.
3303 *
3304 * We furthermore need this type check to handle built-in, immutable
3305 * polymorphic functions such as array_eq().
3306 */
3307 if (exprType(node) >= FirstUnpinnedObjectId)
3308 ereport(ERROR,
3310 errmsg("generation expression uses user-defined type"),
3311 errdetail("Virtual generated columns that make use of user-defined types are not yet supported."),
3312 parser_errposition(pstate, exprLocation(node)));
3313 }
3314
3316}
static bool contains_user_functions_checker(Oid func_id, void *context)
Definition heap.c:3271
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition nodeFuncs.c:1917
int exprLocation(const Node *expr)
Definition nodeFuncs.c:1392
#define FirstUnpinnedObjectId
Definition transam.h:196

References check_functions_in_node(), check_virtual_generated_security_walker(), contains_user_functions_checker(), ereport, errcode(), errdetail(), errmsg, ERROR, expression_tree_walker, exprLocation(), exprType(), fb(), FirstUnpinnedObjectId, IsA, and parser_errposition().

Referenced by check_virtual_generated_security(), and check_virtual_generated_security_walker().

◆ CheckAttributeNamesTypes()

void CheckAttributeNamesTypes ( TupleDesc  tupdesc,
char  relkind,
int  flags 
)

Definition at line 452 of file heap.c.

454{
455 int i;
456 int j;
457 int natts = tupdesc->natts;
458
459 /* Sanity check on column count */
463 errmsg("tables can have at most %d columns",
465
466 /*
467 * first check for collision with system attribute names
468 *
469 * Skip this for a view or type relation, since those don't have system
470 * attributes.
471 */
472 if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
473 {
474 for (i = 0; i < natts; i++)
475 {
476 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
477
478 if (SystemAttributeByName(NameStr(attr->attname)) != NULL)
481 errmsg("column name \"%s\" conflicts with a system column name",
482 NameStr(attr->attname))));
483 }
484 }
485
486 /*
487 * next check for repeated attribute names
488 */
489 for (i = 1; i < natts; i++)
490 {
491 for (j = 0; j < i; j++)
492 {
493 if (strcmp(NameStr(TupleDescAttr(tupdesc, j)->attname),
494 NameStr(TupleDescAttr(tupdesc, i)->attname)) == 0)
497 errmsg("column name \"%s\" specified more than once",
498 NameStr(TupleDescAttr(tupdesc, j)->attname))));
499 }
500 }
501
502 /*
503 * next check the attribute types
504 */
505 for (i = 0; i < natts; i++)
506 {
507 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
508
509 if (attr->attisdropped)
510 continue;
511 CheckAttributeType(NameStr(attr->attname),
512 attr->atttypid,
513 attr->attcollation,
514 NIL, /* assume we're creating a new rowtype */
515 flags | (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL ? CHKATYPE_IS_VIRTUAL : 0));
516 }
517}
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
Definition heap.c:548
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition heap.c:248
#define CHKATYPE_IS_VIRTUAL
Definition heap.h:26
#define MaxHeapAttributeNumber
int j
Definition isn.c:78
NameData attname

References attname, CheckAttributeType(), CHKATYPE_IS_VIRTUAL, ereport, errcode(), errmsg, ERROR, fb(), i, j, MaxHeapAttributeNumber, NameStr, TupleDescData::natts, NIL, SystemAttributeByName(), and TupleDescAttr().

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

◆ CheckAttributeType()

void CheckAttributeType ( const char attname,
Oid  atttypid,
Oid  attcollation,
List containing_rowtypes,
int  flags 
)

Definition at line 548 of file heap.c.

552{
555
556 /* since this function recurses, it could be driven to stack overflow */
558
560 {
561 /*
562 * We disallow pseudo-type columns, with the exception of ANYARRAY,
563 * RECORD, and RECORD[] when the caller says that those are OK.
564 *
565 * We don't need to worry about recursive containment for RECORD and
566 * RECORD[] because (a) no named composite type should be allowed to
567 * contain those, and (b) two "anonymous" record types couldn't be
568 * considered to be the same type, so infinite recursion isn't
569 * possible.
570 */
571 if (!((atttypid == ANYARRAYOID && (flags & CHKATYPE_ANYARRAY)) ||
572 (atttypid == RECORDOID && (flags & CHKATYPE_ANYRECORD)) ||
573 (atttypid == RECORDARRAYOID && (flags & CHKATYPE_ANYRECORD))))
574 {
575 if (flags & CHKATYPE_IS_PARTKEY)
578 /* translator: first %s is an integer not a name */
579 errmsg("partition key column %s has pseudo-type %s",
581 else
584 errmsg("column \"%s\" has pseudo-type %s",
586 }
587 }
588 else if (att_typtype == TYPTYPE_DOMAIN)
589 {
590 /*
591 * Prevent virtual generated columns from having a domain type. We
592 * would have to enforce domain constraints when columns underlying
593 * the generated column change. This could possibly be implemented,
594 * but it's not.
595 */
596 if (flags & CHKATYPE_IS_VIRTUAL)
599 errmsg("virtual generated column \"%s\" cannot have a domain type", attname));
600
601 /*
602 * If it's a domain, recurse to check its base type.
603 */
606 flags);
607 }
608 else if (att_typtype == TYPTYPE_COMPOSITE)
609 {
610 /*
611 * For a composite type, recurse into its attributes.
612 */
613 Relation relation;
614 TupleDesc tupdesc;
615 int i;
616
617 /*
618 * Check for self-containment. Eventually we might be able to allow
619 * this (just return without complaint, if so) but it's not clear how
620 * many other places would require anti-recursion defenses before it
621 * would be safe to allow tables to contain their own rowtype.
622 */
626 errmsg("composite type %s cannot be made a member of itself",
628
630
632
633 tupdesc = RelationGetDescr(relation);
634
635 for (i = 0; i < tupdesc->natts; i++)
636 {
637 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
638
639 if (attr->attisdropped)
640 continue;
641 CheckAttributeType(NameStr(attr->attname),
642 attr->atttypid, attr->attcollation,
644 flags & ~CHKATYPE_IS_PARTKEY);
645 }
646
648
650 }
651 else if (att_typtype == TYPTYPE_RANGE)
652 {
653 /*
654 * If it's a range, recurse to check its subtype.
655 */
659 flags);
660 }
662 {
663 /*
664 * If it's a multirange, recurse to check its plain range type.
665 */
667 InvalidOid, /* range types are not collatable */
669 flags);
670 }
672 {
673 /*
674 * Must recurse into array types, too, in case they are composite.
675 */
678 flags);
679 }
680
681 /*
682 * For consistency with check_virtual_generated_security().
683 */
687 errmsg("virtual generated column \"%s\" cannot have a user-defined type", attname),
688 errdetail("Virtual generated columns that make use of user-defined types are not yet supported."));
689
690 /*
691 * This might not be strictly invalid per SQL standard, but it is pretty
692 * useless, and it cannot be dumped, so we must disallow it.
693 */
694 if (!OidIsValid(attcollation) && type_is_collatable(atttypid))
695 {
696 if (flags & CHKATYPE_IS_PARTKEY)
699 /* translator: first %s is an integer not a name */
700 errmsg("no collation was derived for partition key column %s with collatable type %s",
702 errhint("Use the COLLATE clause to set the collation explicitly.")));
703 else
706 errmsg("no collation was derived for column \"%s\" with collatable type %s",
708 errhint("Use the COLLATE clause to set the collation explicitly.")));
709 }
710}
int errhint(const char *fmt,...) pg_attribute_printf(1
char * format_type_be(Oid type_oid)
#define CHKATYPE_ANYRECORD
Definition heap.h:24
#define CHKATYPE_ANYARRAY
Definition heap.h:23
#define CHKATYPE_IS_PARTKEY
Definition heap.h:25
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
List * list_delete_last(List *list)
Definition list.c:957
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722
Oid get_range_subtype(Oid rangeOid)
Definition lsyscache.c:3602
Oid get_element_type(Oid typid)
Definition lsyscache.c:2954
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3703
Oid get_range_collation(Oid rangeOid)
Definition lsyscache.c:3628
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3276
Oid get_typ_typrelid(Oid typid)
Definition lsyscache.c:2926
char get_typtype(Oid typid)
Definition lsyscache.c:2824
Oid getBaseType(Oid typid)
Definition lsyscache.c:2716
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:48
void check_stack_depth(void)
Definition stack_depth.c:95

References AccessShareLock, attname, check_stack_depth(), CheckAttributeType(), CHKATYPE_ANYARRAY, CHKATYPE_ANYRECORD, CHKATYPE_IS_PARTKEY, CHKATYPE_IS_VIRTUAL, ereport, errcode(), errdetail(), errhint(), errmsg, ERROR, fb(), FirstUnpinnedObjectId, format_type_be(), get_element_type(), get_multirange_range(), get_range_collation(), get_range_subtype(), get_typ_typrelid(), get_typtype(), getBaseType(), i, InvalidOid, lappend_oid(), list_delete_last(), list_member_oid(), NameStr, TupleDescData::natts, OidIsValid, relation_close(), relation_open(), RelationGetDescr, TupleDescAttr(), and type_is_collatable().

Referenced by ATExecAddColumn(), ATPrepAlterColumnType(), CheckAttributeNamesTypes(), CheckAttributeType(), ComputePartitionAttrs(), and ConstructTupleDescriptor().

◆ contains_user_functions_checker()

static bool contains_user_functions_checker ( Oid  func_id,
void context 
)
static

Definition at line 3271 of file heap.c.

3272{
3273 return (func_id >= FirstUnpinnedObjectId);
3274}

References fb(), and FirstUnpinnedObjectId.

Referenced by check_virtual_generated_security_walker().

◆ cookConstraint()

static Node * cookConstraint ( ParseState pstate,
Node raw_constraint,
char relname 
)
static

Definition at line 3418 of file heap.c.

3421{
3422 Node *expr;
3423
3424 /*
3425 * Transform raw parsetree to executable expression.
3426 */
3428
3429 /*
3430 * Make sure it yields a boolean result.
3431 */
3432 expr = coerce_to_boolean(pstate, expr, "CHECK");
3433
3434 /*
3435 * Take care of collations.
3436 */
3437 assign_expr_collations(pstate, expr);
3438
3439 /*
3440 * Make sure no outside relations are referred to (this is probably dead
3441 * code now that add_missing_from is history).
3442 */
3443 if (list_length(pstate->p_rtable) != 1)
3444 ereport(ERROR,
3446 errmsg("only table \"%s\" can be referenced in check constraint",
3447 relname)));
3448
3449 return expr;
3450}
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition parse_expr.c:121
@ EXPR_KIND_CHECK_CONSTRAINT
Definition parse_node.h:69
NameData relname
Definition pg_class.h:40

References assign_expr_collations(), coerce_to_boolean(), ereport, errcode(), errmsg, ERROR, EXPR_KIND_CHECK_CONSTRAINT, fb(), list_length(), ParseState::p_rtable, relname, and transformExpr().

Referenced by AddRelationNewConstraints().

◆ cookDefault()

Node * cookDefault ( ParseState pstate,
Node raw_default,
Oid  atttypid,
int32  atttypmod,
const char attname,
char  attgenerated 
)

Definition at line 3337 of file heap.c.

3343{
3344 Node *expr;
3345
3346 Assert(raw_default != NULL);
3347
3348 /*
3349 * Transform raw parsetree to executable expression.
3350 */
3351 expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
3352
3353 if (attgenerated)
3354 {
3355 /* Disallow refs to other generated columns */
3356 check_nested_generated(pstate, expr);
3357
3358 /* Disallow mutable functions */
3360 ereport(ERROR,
3362 errmsg("generation expression is not immutable")));
3363
3364 /* Check security of expressions for virtual generated column */
3365 if (attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
3367 }
3368 else
3369 {
3370 /*
3371 * For a default expression, transformExpr() should have rejected
3372 * column references.
3373 */
3374 Assert(!contain_var_clause(expr));
3375 }
3376
3377 /*
3378 * Coerce the expression to the correct type and typmod, if given. This
3379 * should match the parser's processing of non-defaulted expressions ---
3380 * see transformAssignedExpr().
3381 */
3382 if (OidIsValid(atttypid))
3383 {
3384 Oid type_id = exprType(expr);
3385
3386 expr = coerce_to_target_type(pstate, expr, type_id,
3387 atttypid, atttypmod,
3390 -1);
3391 if (expr == NULL)
3392 ereport(ERROR,
3394 errmsg("column \"%s\" is of type %s"
3395 " but default expression is of type %s",
3396 attname,
3398 format_type_be(type_id)),
3399 errhint("You will need to rewrite or cast the expression.")));
3400 }
3401
3402 /*
3403 * Finally, take care of collations in the finished expression.
3404 */
3405 assign_expr_collations(pstate, expr);
3406
3407 return expr;
3408}
bool contain_mutable_functions_after_planning(Expr *expr)
Definition clauses.c:503
static void check_virtual_generated_security(ParseState *pstate, Node *node)
Definition heap.c:3319
static void check_nested_generated(ParseState *pstate, Node *node)
Definition heap.c:3239
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
@ EXPR_KIND_COLUMN_DEFAULT
Definition parse_node.h:71
@ EXPR_KIND_GENERATED_COLUMN
Definition parse_node.h:84
@ COERCE_IMPLICIT_CAST
Definition primnodes.h:769
@ COERCION_ASSIGNMENT
Definition primnodes.h:748
bool contain_var_clause(Node *node)
Definition var.c:406

References Assert, assign_expr_collations(), attname, check_nested_generated(), check_virtual_generated_security(), COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, contain_mutable_functions_after_planning(), contain_var_clause(), ereport, errcode(), errhint(), errmsg, ERROR, EXPR_KIND_COLUMN_DEFAULT, EXPR_KIND_GENERATED_COLUMN, exprType(), fb(), format_type_be(), OidIsValid, and transformExpr().

Referenced by AddRelationNewConstraints(), AlterDomainDefault(), and DefineDomain().

◆ CopyStatistics()

void CopyStatistics ( Oid  fromrelid,
Oid  torelid 
)

Definition at line 3456 of file heap.c.

3457{
3458 HeapTuple tup;
3459 SysScanDesc scan;
3460 ScanKeyData key[1];
3463
3465
3466 /* Now search for stat records */
3467 ScanKeyInit(&key[0],
3471
3473 true, NULL, 1, key);
3474
3475 while (HeapTupleIsValid((tup = systable_getnext(scan))))
3476 {
3478
3479 /* make a modifiable copy */
3482
3483 /* update the copy of the tuple and insert it */
3484 statform->starelid = torelid;
3485
3486 /* fetch index information when we know we need it */
3487 if (indstate == NULL)
3489
3491
3493 }
3494
3495 systable_endscan(scan);
3496
3497 if (indstate != NULL)
3500}
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:612
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:523
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:686
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition indexing.c:256
FormData_pg_statistic * Form_pg_statistic
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
#define BTEqualStrategyNumber
Definition stratnum.h:31

References BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTupleInsertWithInfo(), fb(), GETSTRUCT(), heap_copytuple(), heap_freetuple(), HeapTupleIsValid, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by index_concurrently_swap().

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

Definition at line 1619 of file heap.c.

1620{
1622 SysScanDesc scan;
1623 ScanKeyData key[1];
1625
1626 /* Grab an appropriate lock on the pg_attribute relation */
1628
1629 /* Use the index to scan only attributes of the target relation */
1630 ScanKeyInit(&key[0],
1633 ObjectIdGetDatum(relid));
1634
1636 NULL, 1, key);
1637
1638 /* Delete all the matching tuples */
1639 while ((atttup = systable_getnext(scan)) != NULL)
1640 CatalogTupleDelete(attrel, &atttup->t_self);
1641
1642 /* Clean up after the scan */
1643 systable_endscan(scan);
1645}
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365

References BTEqualStrategyNumber, CatalogTupleDelete(), fb(), ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by heap_drop_with_catalog(), and index_drop().

◆ DeleteRelationTuple()

void DeleteRelationTuple ( Oid  relid)

Definition at line 1590 of file heap.c.

1591{
1593 HeapTuple tup;
1594
1595 /* Grab an appropriate lock on the pg_class relation */
1597
1599 if (!HeapTupleIsValid(tup))
1600 elog(ERROR, "cache lookup failed for relation %u", relid);
1601
1602 /* delete the relation tuple from pg_class, and finish up */
1604
1606
1608}
#define elog(elevel,...)
Definition elog.h:228
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221

References CatalogTupleDelete(), elog, ERROR, fb(), HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), table_close(), and table_open().

Referenced by heap_drop_with_catalog(), and index_drop().

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

Definition at line 1656 of file heap.c.

1657{
1659 SysScanDesc scan;
1660 ScanKeyData key[2];
1662
1663 /* Grab an appropriate lock on the pg_attribute relation */
1665
1666 /* Use the index to scan only system attributes of the target relation */
1667 ScanKeyInit(&key[0],
1670 ObjectIdGetDatum(relid));
1671 ScanKeyInit(&key[1],
1674 Int16GetDatum(0));
1675
1677 NULL, 2, key);
1678
1679 /* Delete all the matching tuples */
1680 while ((atttup = systable_getnext(scan)) != NULL)
1681 CatalogTupleDelete(attrel, &atttup->t_self);
1682
1683 /* Clean up after the scan */
1684 systable_endscan(scan);
1686}
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
#define BTLessEqualStrategyNumber
Definition stratnum.h:30

References BTEqualStrategyNumber, BTLessEqualStrategyNumber, CatalogTupleDelete(), fb(), Int16GetDatum(), ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

◆ heap_create()

Relation heap_create ( const char relname,
Oid  relnamespace,
Oid  reltablespace,
Oid  relid,
RelFileNumber  relfilenumber,
Oid  accessmtd,
TupleDesc  tupDesc,
char  relkind,
char  relpersistence,
bool  shared_relation,
bool  mapped_relation,
bool  allow_system_table_mods,
TransactionId relfrozenxid,
MultiXactId relminmxid,
bool  create_storage 
)

Definition at line 285 of file heap.c.

300{
301 Relation rel;
302
303 /* The caller must have provided an OID for the relation. */
304 Assert(OidIsValid(relid));
305
306 /*
307 * Don't allow creating relations in pg_catalog directly, even though it
308 * is allowed to move user defined relations there. Semantics with search
309 * paths including pg_catalog are too confusing for now.
310 *
311 * But allow creating indexes on relations in pg_catalog even if
312 * allow_system_table_mods = off, upper layers already guarantee it's on a
313 * user defined relation, not a system one.
314 */
316 ((IsCatalogNamespace(relnamespace) && relkind != RELKIND_INDEX) ||
317 IsToastNamespace(relnamespace)) &&
321 errmsg("permission denied to create \"%s.%s\"",
322 get_namespace_name(relnamespace), relname),
323 errdetail("System catalog modifications are currently disallowed.")));
324
325 *relfrozenxid = InvalidTransactionId;
326 *relminmxid = InvalidMultiXactId;
327
328 /*
329 * Force reltablespace to zero if the relation kind does not support
330 * tablespaces. This is mainly just for cleanliness' sake.
331 */
332 if (!RELKIND_HAS_TABLESPACE(relkind))
333 reltablespace = InvalidOid;
334
335 /* Don't create storage for relkinds without physical storage. */
336 if (!RELKIND_HAS_STORAGE(relkind))
337 create_storage = false;
338 else
339 {
340 /*
341 * If relfilenumber is unspecified by the caller then create storage
342 * with oid same as relid.
343 */
344 if (!RelFileNumberIsValid(relfilenumber))
345 relfilenumber = relid;
346 }
347
348 /*
349 * Never allow a pg_class entry to explicitly specify the database's
350 * default tablespace in reltablespace; force it to zero instead. This
351 * ensures that if the database is cloned with a different default
352 * tablespace, the pg_class entry will still match where CREATE DATABASE
353 * will put the physically copied relation.
354 *
355 * Yes, this is a bit of a hack.
356 */
357 if (reltablespace == MyDatabaseTableSpace)
358 reltablespace = InvalidOid;
359
360 /*
361 * build the relcache entry.
362 */
364 relnamespace,
365 tupDesc,
366 relid,
367 accessmtd,
368 relfilenumber,
369 reltablespace,
372 relpersistence,
373 relkind);
374
375 /*
376 * Have the storage manager create the relation's disk file, if needed.
377 *
378 * For tables, the AM callback creates both the main and the init fork.
379 * For others, only the main fork is created; the other forks will be
380 * created on demand.
381 */
382 if (create_storage)
383 {
384 if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
386 relpersistence,
387 relfrozenxid, relminmxid);
388 else if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
389 RelationCreateStorage(rel->rd_locator, relpersistence, true);
390 else
391 Assert(false);
392 }
393
394 /*
395 * If a tablespace is specified, removal of that tablespace is normally
396 * protected by the existence of a physical file; but for relations with
397 * no files, add a pg_shdepend entry to account for that.
398 */
399 if (!create_storage && reltablespace != InvalidOid)
401 reltablespace);
402
403 /* ensure that stats are dropped if transaction aborts */
405
406 return rel;
407}
bool IsToastNamespace(Oid namespaceId)
Definition catalog.c:261
bool IsCatalogNamespace(Oid namespaceId)
Definition catalog.c:243
Oid MyDatabaseTableSpace
Definition globals.c:98
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3561
#define IsNormalProcessingMode()
Definition miscadmin.h:497
#define InvalidMultiXactId
Definition multixact.h:25
void recordDependencyOnTablespace(Oid classId, Oid objectId, Oid tablespace)
void pgstat_create_relation(Relation rel)
Relation RelationBuildLocalRelation(const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid accessmtd, RelFileNumber relfilenumber, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
Definition relcache.c:3505
#define RelFileNumberIsValid(relnumber)
Definition relpath.h:27
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
Definition storage.c:122
RelFileLocator rd_locator
Definition rel.h:57
Form_pg_class rd_rel
Definition rel.h:111
static void table_relation_set_new_filelocator(Relation rel, const RelFileLocator *newrlocator, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition tableam.h:1687
#define InvalidTransactionId
Definition transam.h:31

References Assert, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), get_namespace_name(), InvalidMultiXactId, InvalidOid, InvalidTransactionId, IsCatalogNamespace(), IsNormalProcessingMode, IsToastNamespace(), MyDatabaseTableSpace, OidIsValid, pgstat_create_relation(), RelationData::rd_locator, RelationData::rd_rel, recordDependencyOnTablespace(), RelationBuildLocalRelation(), RelationCreateStorage(), RelFileNumberIsValid, relname, and table_relation_set_new_filelocator().

Referenced by heap_create_with_catalog(), and index_create().

◆ heap_create_with_catalog()

Oid heap_create_with_catalog ( const char relname,
Oid  relnamespace,
Oid  reltablespace,
Oid  relid,
Oid  reltypeid,
Oid  reloftypeid,
Oid  ownerid,
Oid  accessmtd,
TupleDesc  tupdesc,
List cooked_constraints,
char  relkind,
char  relpersistence,
bool  shared_relation,
bool  mapped_relation,
OnCommitAction  oncommit,
Datum  reloptions,
bool  use_user_acl,
bool  allow_system_table_mods,
bool  is_internal,
Oid  relrewrite,
ObjectAddress typaddress 
)

Definition at line 1136 of file heap.c.

1157{
1160 Acl *relacl;
1164
1165 /* By default set to InvalidOid unless overridden by binary-upgrade */
1166 RelFileNumber relfilenumber = InvalidRelFileNumber;
1167 TransactionId relfrozenxid;
1168 MultiXactId relminmxid;
1169
1171
1172 /*
1173 * sanity checks
1174 */
1176
1177 /*
1178 * Validate proposed tupdesc for the desired relkind. If
1179 * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
1180 * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
1181 */
1182 CheckAttributeNamesTypes(tupdesc, relkind,
1184
1185 /*
1186 * This would fail later on anyway, if the relation already exists. But
1187 * by catching it here we can emit a nicer error message.
1188 */
1189 existing_relid = get_relname_relid(relname, relnamespace);
1191 ereport(ERROR,
1193 errmsg("relation \"%s\" already exists", relname)));
1194
1195 /*
1196 * Since we are going to create a rowtype as well, also check for
1197 * collision with an existing type name. If there is one and it's an
1198 * autogenerated array, we can rename it out of the way; otherwise we can
1199 * at least give a good error message.
1200 */
1203 ObjectIdGetDatum(relnamespace));
1205 {
1206 if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
1207 ereport(ERROR,
1209 errmsg("type \"%s\" already exists", relname),
1210 errhint("A relation has an associated type of the same name, "
1211 "so you must use a name that doesn't conflict "
1212 "with any existing type.")));
1213 }
1214
1215 /*
1216 * Shared relations must be in pg_global (last-ditch check)
1217 */
1218 if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
1219 elog(ERROR, "shared relations must be placed in pg_global tablespace");
1220
1221 /*
1222 * Allocate an OID for the relation, unless we were told what to use.
1223 *
1224 * The OID will be the relfilenumber as well, so make sure it doesn't
1225 * collide with either pg_class OIDs or existing physical files.
1226 */
1227 if (!OidIsValid(relid))
1228 {
1229 /* Use binary-upgrade override for pg_class.oid and relfilenumber */
1230 if (IsBinaryUpgrade)
1231 {
1232 /*
1233 * Indexes are not supported here; they use
1234 * binary_upgrade_next_index_pg_class_oid.
1235 */
1236 Assert(relkind != RELKIND_INDEX);
1238
1239 if (relkind == RELKIND_TOASTVALUE)
1240 {
1241 /* There might be no TOAST table, so we have to test for it. */
1243 {
1246
1248 ereport(ERROR,
1250 errmsg("toast relfilenumber value not set when in binary upgrade mode")));
1251
1254 }
1255 }
1256 else
1257 {
1259 ereport(ERROR,
1261 errmsg("pg_class heap OID value not set when in binary upgrade mode")));
1262
1265
1266 if (RELKIND_HAS_STORAGE(relkind))
1267 {
1269 ereport(ERROR,
1271 errmsg("relfilenumber value not set when in binary upgrade mode")));
1272
1275 }
1276 }
1277 }
1278
1279 if (!OidIsValid(relid))
1280 relid = GetNewRelFileNumber(reltablespace, pg_class_desc,
1281 relpersistence);
1282 }
1283
1284 /*
1285 * Other sessions' catalog scans can't find this until we commit. Hence,
1286 * it doesn't hurt to hold AccessExclusiveLock. Do it here so callers
1287 * can't accidentally vary in their lock mode or acquisition timing.
1288 */
1290
1291 /*
1292 * Determine the relation's initial permissions.
1293 */
1294 if (use_user_acl)
1295 {
1296 switch (relkind)
1297 {
1298 case RELKIND_RELATION:
1299 case RELKIND_VIEW:
1300 case RELKIND_MATVIEW:
1304 relnamespace);
1305 break;
1306 case RELKIND_SEQUENCE:
1308 relnamespace);
1309 break;
1310 default:
1311 relacl = NULL;
1312 break;
1313 }
1314 }
1315 else
1316 relacl = NULL;
1317
1318 /*
1319 * Create the relcache entry (mostly dummy at this point) and the physical
1320 * disk file. (If we fail further down, it's the smgr's responsibility to
1321 * remove the disk file again.)
1322 *
1323 * NB: Note that passing create_storage = true is correct even for binary
1324 * upgrade. The storage we create here will be replaced later, but we
1325 * need to have something on disk in the meanwhile.
1326 */
1328 relnamespace,
1329 reltablespace,
1330 relid,
1331 relfilenumber,
1332 accessmtd,
1333 tupdesc,
1334 relkind,
1335 relpersistence,
1339 &relfrozenxid,
1340 &relminmxid,
1341 true);
1342
1344
1345 new_rel_desc->rd_rel->relrewrite = relrewrite;
1346
1347 /*
1348 * Decide whether to create a pg_type entry for the relation's rowtype.
1349 * These types are made except where the use of a relation as such is an
1350 * implementation detail: toast tables, sequences and indexes.
1351 */
1352 if (!(relkind == RELKIND_SEQUENCE ||
1353 relkind == RELKIND_TOASTVALUE ||
1354 relkind == RELKIND_INDEX ||
1355 relkind == RELKIND_PARTITIONED_INDEX))
1356 {
1359 char *relarrayname;
1360
1361 /*
1362 * We'll make an array over the composite type, too. For largely
1363 * historical reasons, the array type's OID is assigned first.
1364 */
1366
1367 /*
1368 * Make the pg_type entry for the composite type. The OID of the
1369 * composite type can be preselected by the caller, but if reltypeid
1370 * is InvalidOid, we'll generate a new OID for it.
1371 *
1372 * NOTE: we could get a unique-index failure here, in case someone
1373 * else is creating the same type name in parallel but hadn't
1374 * committed yet when we checked for a duplicate name above.
1375 */
1377 relnamespace,
1378 relid,
1379 relkind,
1380 ownerid,
1381 reltypeid,
1383 new_type_oid = new_type_addr.objectId;
1384 if (typaddress)
1386
1387 /* Now create the array type. */
1388 relarrayname = makeArrayTypeName(relname, relnamespace);
1389
1390 TypeCreate(new_array_oid, /* force the type's OID to this */
1391 relarrayname, /* Array type name */
1392 relnamespace, /* Same namespace as parent */
1393 InvalidOid, /* Not composite, no relationOid */
1394 0, /* relkind, also N/A here */
1395 ownerid, /* owner's ID */
1396 -1, /* Internal size (varlena) */
1397 TYPTYPE_BASE, /* Not composite - typelem is */
1398 TYPCATEGORY_ARRAY, /* type-category (array) */
1399 false, /* array types are never preferred */
1400 DEFAULT_TYPDELIM, /* default array delimiter */
1401 F_ARRAY_IN, /* array input proc */
1402 F_ARRAY_OUT, /* array output proc */
1403 F_ARRAY_RECV, /* array recv (bin) proc */
1404 F_ARRAY_SEND, /* array send (bin) proc */
1405 InvalidOid, /* typmodin procedure - none */
1406 InvalidOid, /* typmodout procedure - none */
1407 F_ARRAY_TYPANALYZE, /* array analyze procedure */
1408 F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
1409 new_type_oid, /* array element type - the rowtype */
1410 true, /* yes, this is an array type */
1411 InvalidOid, /* this has no array type */
1412 InvalidOid, /* domain base type - irrelevant */
1413 NULL, /* default value - none */
1414 NULL, /* default binary representation */
1415 false, /* passed by reference */
1416 TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1417 TYPSTORAGE_EXTENDED, /* fully TOASTable */
1418 -1, /* typmod */
1419 0, /* array dimensions for typBaseType */
1420 false, /* Type NOT NULL */
1421 InvalidOid); /* rowtypes never have a collation */
1422
1424 }
1425 else
1426 {
1427 /* Caller should not be expecting a type to be created. */
1430
1432 }
1433
1434 /*
1435 * now create an entry in pg_class for the relation.
1436 *
1437 * NOTE: we could get a unique-index failure here, in case someone else is
1438 * creating the same relation name in parallel but hadn't committed yet
1439 * when we checked for a duplicate name above.
1440 */
1443 relid,
1446 ownerid,
1447 relkind,
1448 relfrozenxid,
1449 relminmxid,
1451 reloptions);
1452
1453 /*
1454 * now add tuples to pg_attribute for the attributes in our new relation.
1455 */
1456 AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
1457
1458 /*
1459 * Make a dependency link to force the relation to be deleted if its
1460 * namespace is. Also make a dependency link to its owner, as well as
1461 * dependencies for any roles mentioned in the default ACL.
1462 *
1463 * For composite types, these dependencies are tracked for the pg_type
1464 * entry, so we needn't record them here. Likewise, TOAST tables don't
1465 * need a namespace dependency (they live in a pinned namespace) nor an
1466 * owner dependency (they depend indirectly through the parent table), nor
1467 * should they have any ACL entries. The same applies for extension
1468 * dependencies.
1469 *
1470 * Also, skip this in bootstrap mode, since we don't make dependencies
1471 * while bootstrapping.
1472 */
1473 if (relkind != RELKIND_COMPOSITE_TYPE &&
1474 relkind != RELKIND_TOASTVALUE &&
1476 {
1478 referenced;
1479 ObjectAddresses *addrs;
1480
1482
1484
1486
1488
1489 addrs = new_object_addresses();
1490
1493
1494 if (reloftypeid)
1495 {
1498 }
1499
1500 /*
1501 * Make a dependency link to force the relation to be deleted if its
1502 * access method is.
1503 *
1504 * No need to add an explicit dependency for the toast table, as the
1505 * main table depends on it. Partitioned tables may not have an
1506 * access method set.
1507 */
1508 if ((RELKIND_HAS_TABLE_AM(relkind) && relkind != RELKIND_TOASTVALUE) ||
1510 {
1513 }
1514
1516 free_object_addresses(addrs);
1517 }
1518
1519 /* Post creation hook for new relation */
1520 InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
1521
1522 /*
1523 * Store any supplied CHECK constraints and defaults.
1524 *
1525 * NB: this may do a CommandCounterIncrement and rebuild the relcache
1526 * entry, so the relation must be valid and self-consistent at this point.
1527 * In particular, there are not yet constraints and defaults anywhere.
1528 */
1530
1531 /*
1532 * If there's a special on-commit action, remember it
1533 */
1534 if (oncommit != ONCOMMIT_NOOP)
1535 register_on_commit_action(relid, oncommit);
1536
1537 /*
1538 * ok, the relation has been cataloged, so close our relations and return
1539 * the OID of the newly created relation.
1540 */
1541 table_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
1543
1544 return relid;
1545}
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition aclchk.c:4370
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition aclchk.c:4290
TransactionId MultiXactId
Definition c.h:746
uint32 TransactionId
Definition c.h:736
RelFileNumber GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
Definition catalog.c:557
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
bool IsBinaryUpgrade
Definition globals.c:123
static void StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
Definition heap.c:2324
static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, char relkind)
Definition heap.c:848
RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber
Definition heap.c:83
static void AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Oid reloftype, Oid relowner, char relkind, TransactionId relfrozenxid, TransactionId relminmxid, Datum relacl, Datum reloptions)
Definition heap.c:998
RelFileNumber binary_upgrade_next_toast_pg_class_relfilenumber
Definition heap.c:84
static ObjectAddress AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type)
Definition heap.c:1057
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, int flags)
Definition heap.c:452
Oid binary_upgrade_next_toast_pg_class_oid
Definition heap.c:82
Oid binary_upgrade_next_heap_pg_class_oid
Definition heap.c:81
Relation heap_create(const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, RelFileNumber relfilenumber, Oid accessmtd, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods, TransactionId *relfrozenxid, MultiXactId *relminmxid, bool create_storage)
Definition heap.c:285
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
#define NoLock
Definition lockdefs.h:34
#define AccessExclusiveLock
Definition lockdefs.h:43
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2078
void pfree(void *pointer)
Definition mcxt.c:1616
#define IsBootstrapProcessingMode()
Definition miscadmin.h:495
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
@ OBJECT_SEQUENCE
@ OBJECT_TABLE
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition pg_depend.c:195
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition pg_type.c:903
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition pg_type.c:838
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
#define PointerGetDatum(X)
Definition postgres.h:354
@ ONCOMMIT_NOOP
Definition primnodes.h:59
Oid RelFileNumber
Definition relpath.h:25
#define InvalidRelFileNumber
Definition relpath.h:26
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111
void register_on_commit_action(Oid relid, OnCommitAction action)
Oid AssignTypeArrayOid(void)
Definition typecmds.c:2473

References AccessExclusiveLock, add_exact_object_address(), AddNewAttributeTuples(), AddNewRelationTuple(), AddNewRelationType(), Assert, AssignTypeArrayOid(), binary_upgrade_next_heap_pg_class_oid, binary_upgrade_next_heap_pg_class_relfilenumber, binary_upgrade_next_toast_pg_class_oid, binary_upgrade_next_toast_pg_class_relfilenumber, CheckAttributeNamesTypes(), CHKATYPE_ANYARRAY, CStringGetDatum(), DEFAULT_TYPDELIM, DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg, ERROR, fb(), free_object_addresses(), get_relname_relid(), get_user_default_acl(), GetNewRelFileNumber(), GetSysCacheOid2, heap_create(), InvalidOid, InvalidRelFileNumber, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, LockRelationOid(), makeArrayTypeName(), moveArrayTypeName(), new_object_addresses(), NoLock, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, ONCOMMIT_NOOP, pfree(), PointerGetDatum, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), recordDependencyOnNewAcl(), recordDependencyOnOwner(), register_on_commit_action(), RelationGetRelid, RelFileNumberIsValid, relname, RowExclusiveLock, StoreConstraints(), table_close(), table_open(), and TypeCreate().

Referenced by create_toast_table(), createPartitionTable(), DefineRelation(), and make_new_heap().

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

Definition at line 1798 of file heap.c.

1799{
1800 Relation rel;
1801 HeapTuple tuple;
1804
1805 /*
1806 * To drop a partition safely, we must grab exclusive lock on its parent,
1807 * because another backend might be about to execute a query on the parent
1808 * table. If it relies on previously cached partition descriptor, then it
1809 * could attempt to access the just-dropped relation as its partition. We
1810 * must therefore take a table lock strong enough to prevent all queries
1811 * on the table from proceeding until we commit and send out a
1812 * shared-cache-inval notice that will make them update their partition
1813 * descriptors.
1814 */
1815 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1816 if (!HeapTupleIsValid(tuple))
1817 elog(ERROR, "cache lookup failed for relation %u", relid);
1818 if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1819 {
1820 /*
1821 * We have to lock the parent if the partition is being detached,
1822 * because it's possible that some query still has a partition
1823 * descriptor that includes this partition.
1824 */
1825 parentOid = get_partition_parent(relid, true);
1827
1828 /*
1829 * If this is not the default partition, dropping it will change the
1830 * default partition's partition constraint, so we must lock it.
1831 */
1833 if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1835 }
1836
1837 ReleaseSysCache(tuple);
1838
1839 /*
1840 * Open and lock the relation.
1841 */
1842 rel = relation_open(relid, AccessExclusiveLock);
1843
1844 /*
1845 * There can no longer be anyone *else* touching the relation, but we
1846 * might still have open queries or cursors, or pending trigger events, in
1847 * our own session.
1848 */
1849 CheckTableNotInUse(rel, "DROP TABLE");
1850
1851 /*
1852 * This effectively deletes all rows in the table, and may be done in a
1853 * serializable transaction. In that case we must record a rw-conflict in
1854 * to this transaction from each transaction holding a predicate lock on
1855 * the table.
1856 */
1858
1859 /*
1860 * Delete pg_foreign_table tuple first.
1861 */
1862 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1863 {
1866
1868
1871 elog(ERROR, "cache lookup failed for foreign table %u", relid);
1872
1873 CatalogTupleDelete(ftrel, &fttuple->t_self);
1874
1877 }
1878
1879 /*
1880 * If a partitioned table, delete the pg_partitioned_table tuple.
1881 */
1882 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1884
1885 /*
1886 * If the relation being dropped is the default partition itself,
1887 * invalidate its entry in pg_partitioned_table.
1888 */
1889 if (relid == defaultPartOid)
1891
1892 /*
1893 * Schedule unlinking of the relation's physical files at commit.
1894 */
1895 if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
1897
1898 /* ensure that stats are dropped if transaction commits */
1900
1901 /*
1902 * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1903 * until transaction commit. This ensures no one else will try to do
1904 * something with the doomed relation.
1905 */
1906 relation_close(rel, NoLock);
1907
1908 /*
1909 * Remove any associated relation synchronization states.
1910 */
1912
1913 /*
1914 * Forget any ON COMMIT action for the rel
1915 */
1917
1918 /*
1919 * Flush the relation from the relcache. We want to do this before
1920 * starting to remove catalog entries, just to be certain that no relcache
1921 * entry rebuild will happen partway through. (That should not really
1922 * matter, since we don't do CommandCounterIncrement here, but let's be
1923 * safe.)
1924 */
1926
1927 /*
1928 * remove inheritance information
1929 */
1931
1932 /*
1933 * delete statistics
1934 */
1935 RemoveStatistics(relid, 0);
1936
1937 /*
1938 * delete attribute tuples
1939 */
1940 DeleteAttributeTuples(relid);
1941
1942 /*
1943 * delete relation tuple
1944 */
1945 DeleteRelationTuple(relid);
1946
1947 if (OidIsValid(parentOid))
1948 {
1949 /*
1950 * If this is not the default partition, the partition constraint of
1951 * the default partition has changed to include the portion of the key
1952 * space previously covered by the dropped partition.
1953 */
1954 if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1956
1957 /*
1958 * Invalidate the parent's relcache so that the partition is no longer
1959 * included in its partition descriptor.
1960 */
1962 /* keep the lock */
1963 }
1964}
void DeleteRelationTuple(Oid relid)
Definition heap.c:1590
void DeleteAttributeTuples(Oid relid)
Definition heap.c:1619
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition heap.c:3509
static void RelationRemoveInheritance(Oid relid)
Definition heap.c:1557
void RemovePartitionKeyByRelId(Oid relid)
Definition heap.c:4037
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition inval.c:1691
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition partition.c:340
Oid get_default_partition_oid(Oid parentId)
Definition partition.c:315
Oid get_partition_parent(Oid relid, bool even_if_detached)
Definition partition.c:53
void RemoveSubscriptionRel(Oid subid, Oid relid)
void pgstat_drop_relation(Relation rel)
void CheckTableForSerializableConflictIn(Relation relation)
Definition predicate.c:4348
void RelationForgetRelation(Oid rid)
Definition relcache.c:2883
void RelationDropStorage(Relation rel)
Definition storage.c:207
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition tablecmds.c:4473
void remove_on_commit_action(Oid relid)

References AccessExclusiveLock, CacheInvalidateRelcacheByRelid(), CatalogTupleDelete(), CheckTableForSerializableConflictIn(), CheckTableNotInUse(), DeleteAttributeTuples(), DeleteRelationTuple(), elog, ERROR, fb(), get_default_partition_oid(), get_partition_parent(), GETSTRUCT(), HeapTupleIsValid, InvalidOid, LockRelationOid(), NoLock, ObjectIdGetDatum(), OidIsValid, pgstat_drop_relation(), RelationData::rd_rel, relation_close(), relation_open(), RelationDropStorage(), RelationForgetRelation(), RelationRemoveInheritance(), ReleaseSysCache(), remove_on_commit_action(), RemovePartitionKeyByRelId(), RemoveStatistics(), RemoveSubscriptionRel(), RowExclusiveLock, SearchSysCache1(), table_close(), table_open(), and update_default_partition_oid().

Referenced by doDeletion().

◆ heap_truncate()

void heap_truncate ( List relids)

Definition at line 3605 of file heap.c.

3606{
3607 List *relations = NIL;
3608 ListCell *cell;
3609
3610 /* Open relations for processing, and grab exclusive access on each */
3611 foreach(cell, relids)
3612 {
3613 Oid rid = lfirst_oid(cell);
3614 Relation rel;
3615
3616 rel = table_open(rid, AccessExclusiveLock);
3617 relations = lappend(relations, rel);
3618 }
3619
3620 /* Don't allow truncate on tables that are referenced by foreign keys */
3621 heap_truncate_check_FKs(relations, true);
3622
3623 /* OK to do it */
3624 foreach(cell, relations)
3625 {
3626 Relation rel = lfirst(cell);
3627
3628 /* Truncate the relation */
3630
3631 /* Close the relation, but keep exclusive lock on it until commit */
3632 table_close(rel, NoLock);
3633 }
3634}
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition heap.c:3690
void heap_truncate_one_rel(Relation rel)
Definition heap.c:3646
#define lfirst(lc)
Definition pg_list.h:172
#define lfirst_oid(lc)
Definition pg_list.h:174

References AccessExclusiveLock, heap_truncate_check_FKs(), heap_truncate_one_rel(), lappend(), lfirst, lfirst_oid, NIL, NoLock, table_close(), and table_open().

Referenced by PreCommit_on_commit_actions().

◆ heap_truncate_check_FKs()

void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

Definition at line 3690 of file heap.c.

3691{
3692 List *oids = NIL;
3694 ListCell *cell;
3695
3696 /*
3697 * Build a list of OIDs of the interesting relations.
3698 *
3699 * If a relation has no triggers, then it can neither have FKs nor be
3700 * referenced by a FK from another table, so we can ignore it. For
3701 * partitioned tables, FKs have no triggers, so we must include them
3702 * anyway.
3703 */
3704 foreach(cell, relations)
3705 {
3706 Relation rel = lfirst(cell);
3707
3708 if (rel->rd_rel->relhastriggers ||
3709 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3710 oids = lappend_oid(oids, RelationGetRelid(rel));
3711 }
3712
3713 /*
3714 * Fast path: if no relation has triggers, none has FKs either.
3715 */
3716 if (oids == NIL)
3717 return;
3718
3719 /*
3720 * Otherwise, must scan pg_constraint. We make one pass with all the
3721 * relations considered; if this finds nothing, then all is well.
3722 */
3724 if (dependents == NIL)
3725 return;
3726
3727 /*
3728 * Otherwise we repeat the scan once per relation to identify a particular
3729 * pair of relations to complain about. This is pretty slow, but
3730 * performance shouldn't matter much in a failure path. The reason for
3731 * doing things this way is to ensure that the message produced is not
3732 * dependent on chance row locations within pg_constraint.
3733 */
3734 foreach(cell, oids)
3735 {
3736 Oid relid = lfirst_oid(cell);
3737 ListCell *cell2;
3738
3740
3741 foreach(cell2, dependents)
3742 {
3744
3745 if (!list_member_oid(oids, relid2))
3746 {
3747 char *relname = get_rel_name(relid);
3748 char *relname2 = get_rel_name(relid2);
3749
3750 if (tempTables)
3751 ereport(ERROR,
3753 errmsg("unsupported ON COMMIT and foreign key combination"),
3754 errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3755 relname2, relname)));
3756 else
3757 ereport(ERROR,
3759 errmsg("cannot truncate a table referenced in a foreign key constraint"),
3760 errdetail("Table \"%s\" references \"%s\".",
3761 relname2, relname),
3762 errhint("Truncate table \"%s\" at the same time, "
3763 "or use TRUNCATE ... CASCADE.",
3764 relname2)));
3765 }
3766 }
3767 }
3768}
List * heap_truncate_find_FKs(List *relationIds)
Definition heap.c:3785
char * get_rel_name(Oid relid)
Definition lsyscache.c:2121
#define list_make1_oid(x1)
Definition pg_list.h:274

References ereport, errcode(), errdetail(), errhint(), errmsg, ERROR, fb(), get_rel_name(), heap_truncate_find_FKs(), lappend_oid(), lfirst, lfirst_oid, list_make1_oid, list_member_oid(), NIL, RelationData::rd_rel, RelationGetRelid, and relname.

Referenced by ExecuteTruncateGuts(), and heap_truncate().

◆ heap_truncate_find_FKs()

List * heap_truncate_find_FKs ( List relationIds)

Definition at line 3785 of file heap.c.

3786{
3787 List *result = NIL;
3788 List *oids;
3790 ListCell *cell;
3794 HeapTuple tuple;
3795 bool restart;
3796
3797 oids = list_copy(relationIds);
3798
3799 /*
3800 * Must scan pg_constraint. Right now, it is a seqscan because there is
3801 * no available index on confrelid.
3802 */
3804
3805restart:
3806 restart = false;
3807 parent_cons = NIL;
3808
3810 NULL, 0, NULL);
3811
3813 {
3815
3816 /* Not a foreign key */
3817 if (con->contype != CONSTRAINT_FOREIGN)
3818 continue;
3819
3820 /* Not referencing one of our list of tables */
3821 if (!list_member_oid(oids, con->confrelid))
3822 continue;
3823
3824 /*
3825 * If this constraint has a parent constraint which we have not seen
3826 * yet, keep track of it for the second loop, below. Tracking parent
3827 * constraints allows us to climb up to the top-level constraint and
3828 * look for all possible relations referencing the partitioned table.
3829 */
3830 if (OidIsValid(con->conparentid) &&
3831 !list_member_oid(parent_cons, con->conparentid))
3832 parent_cons = lappend_oid(parent_cons, con->conparentid);
3833
3834 /*
3835 * Add referencer to result, unless present in input list. (Don't
3836 * worry about dupes: we'll fix that below).
3837 */
3838 if (!list_member_oid(relationIds, con->conrelid))
3839 result = lappend_oid(result, con->conrelid);
3840 }
3841
3843
3844 /*
3845 * Process each parent constraint we found to add the list of referenced
3846 * relations by them to the oids list. If we do add any new such
3847 * relations, redo the first loop above. Also, if we see that the parent
3848 * constraint in turn has a parent, add that so that we process all
3849 * relations in a single additional pass.
3850 */
3851 foreach(cell, parent_cons)
3852 {
3853 Oid parent = lfirst_oid(cell);
3854
3855 ScanKeyInit(&key,
3858 ObjectIdGetDatum(parent));
3859
3861 true, NULL, 1, &key);
3862
3863 tuple = systable_getnext(fkeyScan);
3864 if (HeapTupleIsValid(tuple))
3865 {
3867
3868 /*
3869 * pg_constraint rows always appear for partitioned hierarchies
3870 * this way: on the each side of the constraint, one row appears
3871 * for each partition that points to the top-most table on the
3872 * other side.
3873 *
3874 * Because of this arrangement, we can correctly catch all
3875 * relevant relations by adding to 'parent_cons' all rows with
3876 * valid conparentid, and to the 'oids' list all rows with a zero
3877 * conparentid. If any oids are added to 'oids', redo the first
3878 * loop above by setting 'restart'.
3879 */
3880 if (OidIsValid(con->conparentid))
3882 con->conparentid);
3883 else if (!list_member_oid(oids, con->confrelid))
3884 {
3885 oids = lappend_oid(oids, con->confrelid);
3886 restart = true;
3887 }
3888 }
3889
3891 }
3892
3894 if (restart)
3895 goto restart;
3896
3898 list_free(oids);
3899
3900 /* Now sort and de-duplicate the result list */
3903
3904 return result;
3905}
uint32 result
void list_sort(List *list, list_sort_comparator cmp)
Definition list.c:1674
List * list_append_unique_oid(List *list, Oid datum)
Definition list.c:1380
void list_deduplicate_oid(List *list)
Definition list.c:1495
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition list.c:1703
void list_free(List *list)
Definition list.c:1546
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint

References AccessShareLock, BTEqualStrategyNumber, fb(), Form_pg_constraint, GETSTRUCT(), HeapTupleIsValid, InvalidOid, lappend_oid(), lfirst_oid, list_append_unique_oid(), list_copy(), list_deduplicate_oid(), list_free(), list_member_oid(), list_oid_cmp(), list_sort(), NIL, ObjectIdGetDatum(), OidIsValid, result, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ExecuteTruncateGuts(), and heap_truncate_check_FKs().

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

Definition at line 3646 of file heap.c.

3647{
3649
3650 /*
3651 * Truncate the relation. Partitioned tables have no storage, so there is
3652 * nothing to do for them here.
3653 */
3654 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3655 return;
3656
3657 /* Truncate the underlying relation */
3659
3660 /* If the relation has indexes, truncate the indexes too */
3662
3663 /* If there is a toast table, truncate that too */
3664 toastrelid = rel->rd_rel->reltoastrelid;
3666 {
3668
3671 /* keep the lock... */
3673 }
3674}
static void RelationTruncateIndexes(Relation heapRelation)
Definition heap.c:3556
static void table_relation_nontransactional_truncate(Relation rel)
Definition tableam.h:1705

References AccessExclusiveLock, fb(), NoLock, OidIsValid, RelationData::rd_rel, RelationTruncateIndexes(), table_close(), table_open(), and table_relation_nontransactional_truncate().

Referenced by ExecuteTruncateGuts(), and heap_truncate().

◆ InsertPgAttributeTuples()

void InsertPgAttributeTuples ( Relation  pg_attribute_rel,
TupleDesc  tupdesc,
Oid  new_rel_oid,
const FormExtraData_pg_attribute  tupdesc_extra[],
CatalogIndexState  indstate 
)

Definition at line 731 of file heap.c.

736{
737 TupleTableSlot **slot;
738 TupleDesc td;
739 int nslots;
740 int natts = 0;
741 int slotCount = 0;
742 bool close_index = false;
743
745
746 /* Initialize the number of slots to use */
747 nslots = Min(tupdesc->natts,
749 slot = palloc_array(TupleTableSlot *, nslots);
750 for (int i = 0; i < nslots; i++)
752
753 while (natts < tupdesc->natts)
754 {
755 Form_pg_attribute attrs = TupleDescAttr(tupdesc, natts);
757
759
760 memset(slot[slotCount]->tts_isnull, false,
761 slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool));
762
763 if (new_rel_oid != InvalidOid)
765 else
767
787 if (attrs_extra)
788 {
789 slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.value;
790 slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.isnull;
791
792 slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.value;
793 slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.isnull;
794 }
795 else
796 {
799 }
800
801 /*
802 * The remaining fields are not set for new columns.
803 */
807
809 slotCount++;
810
811 /*
812 * If slots are full or the end of processing has been reached, insert
813 * a batch of tuples.
814 */
815 if (slotCount == nslots || natts == tupdesc->natts - 1)
816 {
817 /* fetch index info only when we know we need it */
818 if (!indstate)
819 {
821 close_index = true;
822 }
823
824 /* insert the new tuples and update the indexes */
826 indstate);
827 slotCount = 0;
828 }
829
830 natts++;
831 }
832
833 if (close_index)
835 for (int i = 0; i < nslots; i++)
837 pfree(slot);
838}
#define Min(x, y)
Definition c.h:1091
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
const TupleTableSlotOps TTSOpsHeapTuple
Definition execTuples.c:85
#define palloc_array(type, count)
Definition fe_memutils.h:76
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition indexing.c:273
#define MAX_CATALOG_MULTI_INSERT_BYTES
Definition indexing.h:33
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:406
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static Datum CharGetDatum(char X)
Definition postgres.h:132
bool * tts_isnull
Definition tuptable.h:133
Datum * tts_values
Definition tuptable.h:131
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:476

References BoolGetDatum(), CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTuplesMultiInsertWithInfo(), CharGetDatum(), ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), fb(), FormData_pg_attribute, i, Int16GetDatum(), Int32GetDatum(), InvalidOid, MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, Min, NameGetDatum(), TupleDescData::natts, ObjectIdGetDatum(), palloc_array, pfree(), RelationGetDescr, TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, TTSOpsHeapTuple, and TupleDescAttr().

Referenced by AddNewAttributeTuples(), AppendAttributeTuples(), and ATExecAddColumn().

◆ InsertPgClassTuple()

void InsertPgClassTuple ( Relation  pg_class_desc,
Relation  new_rel_desc,
Oid  new_rel_oid,
Datum  relacl,
Datum  reloptions 
)

Definition at line 924 of file heap.c.

929{
930 Form_pg_class rd_rel = new_rel_desc->rd_rel;
932 bool nulls[Natts_pg_class];
934
935 /* This is a tad tedious, but way cleaner than what we used to do... */
936 memset(values, 0, sizeof(values));
937 memset(nulls, false, sizeof(nulls));
938
940 values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
941 values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
942 values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
943 values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
944 values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
945 values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
946 values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
947 values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
948 values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
949 values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
950 values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
951 values[Anum_pg_class_relallfrozen - 1] = Int32GetDatum(rd_rel->relallfrozen);
952 values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
953 values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
954 values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
955 values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
956 values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
957 values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
958 values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
959 values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
960 values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
961 values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
962 values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
963 values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
964 values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
965 values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
966 values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
967 values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
968 values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
969 values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
970 if (relacl != (Datum) 0)
972 else
973 nulls[Anum_pg_class_relacl - 1] = true;
974 if (reloptions != (Datum) 0)
975 values[Anum_pg_class_reloptions - 1] = reloptions;
976 else
977 nulls[Anum_pg_class_reloptions - 1] = true;
978
979 /* relpartbound is set by updating this tuple, if necessary */
980 nulls[Anum_pg_class_relpartbound - 1] = true;
981
983
984 /* finally insert the new tuple, update the indexes, and clean up */
986
988}
static Datum values[MAXATTR]
Definition bootstrap.c:190
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
static Datum Float4GetDatum(float4 X)
Definition postgres.h:481
static Datum TransactionIdGetDatum(TransactionId X)
Definition postgres.h:292
static Datum MultiXactIdGetDatum(MultiXactId X)
Definition postgres.h:302
uint64_t Datum
Definition postgres.h:70

References BoolGetDatum(), CatalogTupleInsert(), CharGetDatum(), fb(), Float4GetDatum(), heap_form_tuple(), heap_freetuple(), Int16GetDatum(), Int32GetDatum(), MultiXactIdGetDatum(), NameGetDatum(), ObjectIdGetDatum(), RelationGetDescr, TransactionIdGetDatum(), and values.

Referenced by AddNewRelationTuple(), and index_create().

◆ MergeWithExistingConstraint()

static bool MergeWithExistingConstraint ( Relation  rel,
const char ccname,
Node expr,
bool  allow_merge,
bool  is_local,
bool  is_enforced,
bool  is_initially_valid,
bool  is_no_inherit 
)
static

Definition at line 2726 of file heap.c.

2731{
2732 bool found;
2735 ScanKeyData skey[3];
2736 HeapTuple tup;
2737
2738 /* Search for a pg_constraint entry with same name and relation */
2740
2741 found = false;
2742
2743 ScanKeyInit(&skey[0],
2747 ScanKeyInit(&skey[1],
2751 ScanKeyInit(&skey[2],
2754 CStringGetDatum(ccname));
2755
2757 NULL, 3, skey);
2758
2759 /* There can be at most one matching row */
2761 {
2763
2764 /* Found it. Conflicts if not identical check constraint */
2765 if (con->contype == CONSTRAINT_CHECK)
2766 {
2767 Datum val;
2768 bool isnull;
2769
2772 conDesc->rd_att, &isnull);
2773 if (isnull)
2774 elog(ERROR, "null conbin for rel %s",
2777 found = true;
2778 }
2779
2780 /*
2781 * If the existing constraint is purely inherited (no local
2782 * definition) then interpret addition of a local constraint as a
2783 * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
2784 * tables to be given in either order with same end state. However if
2785 * the relation is a partition, all inherited constraints are always
2786 * non-local, including those that were merged.
2787 */
2788 if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2789 allow_merge = true;
2790
2791 if (!found || !allow_merge)
2792 ereport(ERROR,
2794 errmsg("constraint \"%s\" for relation \"%s\" already exists",
2795 ccname, RelationGetRelationName(rel))));
2796
2797 /* If the child constraint is "no inherit" then cannot merge */
2798 if (con->connoinherit)
2799 ereport(ERROR,
2801 errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2802 ccname, RelationGetRelationName(rel))));
2803
2804 /*
2805 * Must not change an existing inherited constraint to "no inherit"
2806 * status. That's because inherited constraints should be able to
2807 * propagate to lower-level children.
2808 */
2809 if (con->coninhcount > 0 && is_no_inherit)
2810 ereport(ERROR,
2812 errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2813 ccname, RelationGetRelationName(rel))));
2814
2815 /*
2816 * If the child constraint is "not valid" then cannot merge with a
2817 * valid parent constraint.
2818 */
2819 if (is_initially_valid && con->conenforced && !con->convalidated)
2820 ereport(ERROR,
2822 errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2823 ccname, RelationGetRelationName(rel))));
2824
2825 /*
2826 * A non-enforced child constraint cannot be merged with an enforced
2827 * parent constraint. However, the reverse is allowed, where the child
2828 * constraint is enforced.
2829 */
2830 if ((!is_local && is_enforced && !con->conenforced) ||
2831 (is_local && !is_enforced && con->conenforced))
2832 ereport(ERROR,
2834 errmsg("constraint \"%s\" conflicts with NOT ENFORCED constraint on relation \"%s\"",
2835 ccname, RelationGetRelationName(rel))));
2836
2837 /* OK to update the tuple */
2839 (errmsg("merging constraint \"%s\" with inherited definition",
2840 ccname)));
2841
2844
2845 /*
2846 * In case of partitions, an inherited constraint must be inherited
2847 * only once since it cannot have multiple parents and it is never
2848 * considered local.
2849 */
2850 if (rel->rd_rel->relispartition)
2851 {
2852 con->coninhcount = 1;
2853 con->conislocal = false;
2854 }
2855 else
2856 {
2857 if (is_local)
2858 con->conislocal = true;
2859 else if (pg_add_s16_overflow(con->coninhcount, 1,
2860 &con->coninhcount))
2861 ereport(ERROR,
2863 errmsg("too many inheritance parents"));
2864 }
2865
2866 if (is_no_inherit)
2867 {
2868 Assert(is_local);
2869 con->connoinherit = true;
2870 }
2871
2872 /*
2873 * If the child constraint is required to be enforced while the parent
2874 * constraint is not, this should be allowed by marking the child
2875 * constraint as enforced. In the reverse case, an error would have
2876 * already been thrown before reaching this point.
2877 */
2878 if (is_enforced && !con->conenforced)
2879 {
2880 Assert(is_local);
2881 con->conenforced = true;
2882 con->convalidated = true;
2883 }
2884
2885 CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2886 }
2887
2890
2891 return found;
2892}
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NOTICE
Definition elog.h:36
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
long val
Definition informix.c:689
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
Definition int.h:67

References Assert, BTEqualStrategyNumber, CatalogTupleUpdate(), CStringGetDatum(), elog, equal(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg, ERROR, fastgetattr(), fb(), Form_pg_constraint, GETSTRUCT(), heap_copytuple(), HeapTupleIsValid, InvalidOid, NOTICE, ObjectIdGetDatum(), pg_add_s16_overflow(), RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RowExclusiveLock, ScanKeyInit(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, and val.

Referenced by AddRelationNewConstraints().

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

Definition at line 1978 of file heap.c.

1979{
1981 Oid relid = RelationGetRelid(rel);
1982 int natts = RelationGetNumberOfAttributes(rel);
1983 int attnum;
1988 HeapTuple tuple,
1989 newtuple;
1990
1991 memset(repl_val, 0, sizeof(repl_val));
1992 memset(repl_null, false, sizeof(repl_null));
1993 memset(repl_repl, false, sizeof(repl_repl));
1994
1997
2000
2001
2002 /* Get a lock on pg_attribute */
2004
2005 /* process each non-system attribute, including any dropped columns */
2006 for (attnum = 1; attnum <= natts; attnum++)
2007 {
2008 tuple = SearchSysCache2(ATTNUM,
2009 ObjectIdGetDatum(relid),
2011 if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2012 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2013 attnum, relid);
2014
2016
2017 /* ignore any where atthasmissing is not true */
2018 if (attrtuple->atthasmissing)
2019 {
2020 newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2022
2023 CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2024
2025 heap_freetuple(newtuple);
2026 }
2027
2028 ReleaseSysCache(tuple);
2029 }
2030
2031 /*
2032 * Our update of the pg_attribute rows will force a relcache rebuild, so
2033 * there's nothing else to do here.
2034 */
2036}
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1118
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:522
ItemPointerData t_self
Definition htup.h:65
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231

References attnum, BoolGetDatum(), CatalogTupleUpdate(), elog, ERROR, fb(), GETSTRUCT(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum(), ObjectIdGetDatum(), RelationGetDescr, RelationGetNumberOfAttributes, RelationGetRelid, ReleaseSysCache(), RowExclusiveLock, SearchSysCache2(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by ATExecAlterColumnType(), ATExecSetExpression(), and finish_heap_swap().

◆ RelationRemoveInheritance()

◆ RelationTruncateIndexes()

static void RelationTruncateIndexes ( Relation  heapRelation)
static

Definition at line 3556 of file heap.c.

3557{
3559
3560 /* Ask the relcache to produce a list of the indexes of the rel */
3561 foreach(indlist, RelationGetIndexList(heapRelation))
3562 {
3565 IndexInfo *indexInfo;
3566
3567 /* Open the index relation; use exclusive lock, just to be sure */
3569
3570 /*
3571 * Fetch info needed for index_build. Since we know there are no
3572 * tuples that actually need indexing, we can use a dummy IndexInfo.
3573 * This is slightly cheaper to build, but the real point is to avoid
3574 * possibly running user-defined code in index expressions or
3575 * predicates. We might be getting invoked during ON COMMIT
3576 * processing, and we don't want to run any such code then.
3577 */
3578 indexInfo = BuildDummyIndexInfo(currentIndex);
3579
3580 /*
3581 * Now truncate the actual file (and discard buffers).
3582 */
3584
3585 /* Initialize the index and rebuild */
3586 /* Note: we do not need to re-establish pkey setting */
3587 index_build(heapRelation, currentIndex, indexInfo, true, false,
3588 true);
3589
3590 /* We're done with this index */
3592 }
3593}
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isreindex, bool parallel, bool progress)
Definition index.c:3021
IndexInfo * BuildDummyIndexInfo(Relation index)
Definition index.c:2506
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:178
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:134
List * RelationGetIndexList(Relation relation)
Definition relcache.c:4827
void RelationTruncate(Relation rel, BlockNumber nblocks)
Definition storage.c:289

References AccessExclusiveLock, BuildDummyIndexInfo(), fb(), index_build(), index_close(), index_open(), lfirst_oid, NoLock, RelationGetIndexList(), and RelationTruncate().

Referenced by heap_truncate_one_rel().

◆ RemoveAttributeById()

void RemoveAttributeById ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 1697 of file heap.c.

1698{
1699 Relation rel;
1701 HeapTuple tuple;
1703 char newattname[NAMEDATALEN];
1705 bool nullsAtt[Natts_pg_attribute] = {0};
1706 bool replacesAtt[Natts_pg_attribute] = {0};
1707
1708 /*
1709 * Grab an exclusive lock on the target table, which we will NOT release
1710 * until end of transaction. (In the simple case where we are directly
1711 * dropping this column, ATExecDropColumn already did this ... but when
1712 * cascading from a drop of some other object, we may not have any lock.)
1713 */
1714 rel = relation_open(relid, AccessExclusiveLock);
1715
1717
1719 ObjectIdGetDatum(relid),
1721 if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1722 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1723 attnum, relid);
1725
1726 /* Mark the attribute as dropped */
1727 attStruct->attisdropped = true;
1728
1729 /*
1730 * Set the type OID to invalid. A dropped attribute's type link cannot be
1731 * relied on (once the attribute is dropped, the type might be too).
1732 * Fortunately we do not need the type row --- the only really essential
1733 * information is the type's typlen and typalign, which are preserved in
1734 * the attribute's attlen and attalign. We set atttypid to zero here as a
1735 * means of catching code that incorrectly expects it to be valid.
1736 */
1737 attStruct->atttypid = InvalidOid;
1738
1739 /* Remove any not-null constraint the column may have */
1740 attStruct->attnotnull = false;
1741
1742 /* Unset this so no one tries to look up the generation expression */
1743 attStruct->attgenerated = '\0';
1744
1745 /*
1746 * Change the column name to something that isn't likely to conflict
1747 */
1749 "........pg.dropped.%d........", attnum);
1750 namestrcpy(&(attStruct->attname), newattname);
1751
1752 /* Clear the missing value */
1753 attStruct->atthasmissing = false;
1756
1757 /*
1758 * Clear the other nullable fields. This saves some space in pg_attribute
1759 * and removes no longer useful information.
1760 */
1769
1772
1773 CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1774
1775 /*
1776 * Because updating the pg_attribute row will trigger a relcache flush for
1777 * the target relation, we need not do anything else to notify other
1778 * backends of the change.
1779 */
1780
1782
1783 RemoveStatistics(relid, attnum);
1784
1785 relation_close(rel, NoLock);
1786}
void namestrcpy(Name name, const char *str)
Definition name.c:233
#define NAMEDATALEN
#define snprintf
Definition port.h:260
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition syscache.h:93

References AccessExclusiveLock, attnum, CatalogTupleUpdate(), elog, ERROR, fb(), GETSTRUCT(), heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum(), InvalidOid, NAMEDATALEN, namestrcpy(), NoLock, ObjectIdGetDatum(), relation_close(), relation_open(), RelationGetDescr, RemoveStatistics(), RowExclusiveLock, SearchSysCacheCopy2, snprintf, HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

Definition at line 4037 of file heap.c.

4038{
4039 Relation rel;
4040 HeapTuple tuple;
4041
4043
4045 if (!HeapTupleIsValid(tuple))
4046 elog(ERROR, "cache lookup failed for partition key of relation %u",
4047 relid);
4048
4049 CatalogTupleDelete(rel, &tuple->t_self);
4050
4051 ReleaseSysCache(tuple);
4053}

References CatalogTupleDelete(), elog, ERROR, fb(), HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by heap_drop_with_catalog().

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 3509 of file heap.c.

3510{
3512 SysScanDesc scan;
3513 ScanKeyData key[2];
3514 int nkeys;
3515 HeapTuple tuple;
3516
3518
3519 ScanKeyInit(&key[0],
3522 ObjectIdGetDatum(relid));
3523
3524 if (attnum == 0)
3525 nkeys = 1;
3526 else
3527 {
3528 ScanKeyInit(&key[1],
3532 nkeys = 2;
3533 }
3534
3536 NULL, nkeys, key);
3537
3538 /* we must loop even when attnum != 0, in case of inherited stats */
3539 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3541
3542 systable_endscan(scan);
3543
3545}

References attnum, BTEqualStrategyNumber, CatalogTupleDelete(), fb(), HeapTupleIsValid, Int16GetDatum(), ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by ATExecAlterColumnType(), ATExecSetExpression(), heap_drop_with_catalog(), index_drop(), and RemoveAttributeById().

◆ SetAttrMissing()

void SetAttrMissing ( Oid  relid,
char attname,
char value 
)

Definition at line 2100 of file heap.c.

2101{
2103 bool nullsAtt[Natts_pg_attribute] = {0};
2104 bool replacesAtt[Natts_pg_attribute] = {0};
2108 tablerel;
2110 newtup;
2111
2112 /* lock the table the attribute belongs to */
2114
2115 /* Don't do anything unless it's a plain table */
2116 if (tablerel->rd_rel->relkind != RELKIND_RELATION)
2117 {
2119 return;
2120 }
2121
2122 /* Lock the attribute row and get the data */
2126 elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2127 attname, relid);
2129
2130 /* get an array value from the value string */
2133 ObjectIdGetDatum(attStruct->atttypid),
2134 Int32GetDatum(attStruct->atttypmod));
2135
2136 /* update the tuple - set atthasmissing and attmissingval */
2141
2145
2146 /* clean up */
2150}
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition fmgr.h:726
static struct @177 value
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition syscache.c:476

References AccessExclusiveLock, attname, BoolGetDatum(), CatalogTupleUpdate(), CStringGetDatum(), elog, ERROR, fb(), GETSTRUCT(), heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum(), ObjectIdGetDatum(), OidFunctionCall3, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCacheAttName(), table_close(), table_open(), and value.

Referenced by binary_upgrade_set_missing_value().

◆ SetRelationNumChecks()

static void SetRelationNumChecks ( Relation  rel,
int  numchecks 
)
static

Definition at line 3163 of file heap.c.

3164{
3168
3173 elog(ERROR, "cache lookup failed for relation %u",
3174 RelationGetRelid(rel));
3176
3177 if (relStruct->relchecks != numchecks)
3178 {
3179 relStruct->relchecks = numchecks;
3180
3182 }
3183 else
3184 {
3185 /* Skip the disk update, but force relcache inval anyway */
3187 }
3188
3191}
void CacheInvalidateRelcache(Relation relation)
Definition inval.c:1635
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91

References CacheInvalidateRelcache(), CatalogTupleUpdate(), elog, ERROR, fb(), GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, ObjectIdGetDatum(), RelationGetRelid, RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by AddRelationNewConstraints(), and StoreConstraints().

◆ StoreAttrMissingVal()

void StoreAttrMissingVal ( Relation  rel,
AttrNumber  attnum,
Datum  missingval 
)

Definition at line 2044 of file heap.c.

2045{
2047 bool nullsAtt[Natts_pg_attribute] = {0};
2048 bool replacesAtt[Natts_pg_attribute] = {0};
2052 newtup;
2053
2054 /* This is only supported for plain tables */
2055 Assert(rel->rd_rel->relkind == RELKIND_RELATION);
2056
2057 /* Fetch the pg_attribute row */
2059
2063 if (!HeapTupleIsValid(atttup)) /* shouldn't happen */
2064 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2065 attnum, RelationGetRelid(rel));
2067
2068 /* Make a one-element array containing the value */
2070 1,
2071 attStruct->atttypid,
2072 attStruct->attlen,
2073 attStruct->attbyval,
2074 attStruct->attalign));
2075
2076 /* Update the pg_attribute row */
2079
2082
2086
2087 /* clean up */
2090}
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)

References Assert, attnum, BoolGetDatum(), CatalogTupleUpdate(), construct_array(), elog, ERROR, fb(), GETSTRUCT(), heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum(), ObjectIdGetDatum(), PointerGetDatum, RelationData::rd_rel, RelationGetDescr, RelationGetRelid, ReleaseSysCache(), RowExclusiveLock, SearchSysCache2(), table_close(), and table_open().

Referenced by ATExecAddColumn().

◆ StoreConstraints()

static void StoreConstraints ( Relation  rel,
List cooked_constraints,
bool  is_internal 
)
static

Definition at line 2324 of file heap.c.

2325{
2326 int numchecks = 0;
2327 ListCell *lc;
2328
2329 if (cooked_constraints == NIL)
2330 return; /* nothing to do */
2331
2332 /*
2333 * Deparsing of constraint expressions will fail unless the just-created
2334 * pg_attribute tuples for this relation are made visible. So, bump the
2335 * command counter. CAUTION: this will cause a relcache entry rebuild.
2336 */
2338
2339 foreach(lc, cooked_constraints)
2340 {
2342
2343 switch (con->contype)
2344 {
2345 case CONSTR_DEFAULT:
2346 con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
2347 is_internal);
2348 break;
2349 case CONSTR_CHECK:
2350 con->conoid =
2351 StoreRelCheck(rel, con->name, con->expr,
2352 con->is_enforced, !con->skip_validation,
2353 con->is_local, con->inhcount,
2354 con->is_no_inherit, is_internal);
2355 numchecks++;
2356 break;
2357
2358 default:
2359 elog(ERROR, "unrecognized constraint type: %d",
2360 (int) con->contype);
2361 }
2362 }
2363
2364 if (numchecks > 0)
2366}
char * name
Definition heap.h:40
AttrNumber attnum
Definition heap.h:41
bool skip_validation
Definition heap.h:44
bool is_enforced
Definition heap.h:43
bool is_no_inherit
Definition heap.h:47
int16 inhcount
Definition heap.h:46
bool is_local
Definition heap.h:45
ConstrType contype
Definition heap.h:37
Node * expr
Definition heap.h:42
void CommandCounterIncrement(void)
Definition xact.c:1130

References CookedConstraint::attnum, CommandCounterIncrement(), CookedConstraint::conoid, CONSTR_CHECK, CONSTR_DEFAULT, CookedConstraint::contype, elog, ERROR, CookedConstraint::expr, fb(), CookedConstraint::inhcount, CookedConstraint::is_enforced, CookedConstraint::is_local, CookedConstraint::is_no_inherit, lfirst, CookedConstraint::name, NIL, SetRelationNumChecks(), CookedConstraint::skip_validation, StoreAttrDefault(), and StoreRelCheck().

Referenced by heap_create_with_catalog().

◆ StorePartitionBound()

void StorePartitionBound ( Relation  rel,
Relation  parent,
PartitionBoundSpec bound 
)

Definition at line 4068 of file heap.c.

4069{
4071 HeapTuple tuple,
4072 newtuple;
4077
4078 /* Update pg_class tuple */
4082 if (!HeapTupleIsValid(tuple))
4083 elog(ERROR, "cache lookup failed for relation %u",
4084 RelationGetRelid(rel));
4085
4086#ifdef USE_ASSERT_CHECKING
4087 {
4089 bool isnull;
4090
4092 Assert(!classForm->relispartition);
4094 &isnull);
4095 Assert(isnull);
4096 }
4097#endif
4098
4099 /* Fill in relpartbound value */
4100 memset(new_val, 0, sizeof(new_val));
4101 memset(new_null, false, sizeof(new_null));
4102 memset(new_repl, false, sizeof(new_repl));
4106 newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
4108 /* Also set the flag */
4109 ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
4110
4111 /*
4112 * We already checked for no inheritance children, but reset
4113 * relhassubclass in case it was left over.
4114 */
4115 if (rel->rd_rel->relkind == RELKIND_RELATION && rel->rd_rel->relhassubclass)
4116 ((Form_pg_class) GETSTRUCT(newtuple))->relhassubclass = false;
4117
4118 CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
4119 heap_freetuple(newtuple);
4121
4122 /*
4123 * If we're storing bounds for the default partition, update
4124 * pg_partitioned_table too.
4125 */
4126 if (bound->is_default)
4128 RelationGetRelid(rel));
4129
4130 /* Make these updates visible */
4132
4133 /*
4134 * The partition constraint for the default partition depends on the
4135 * partition bounds of every other partition, so we must invalidate the
4136 * relcache entry for that partition every time a partition is added or
4137 * removed.
4138 */
4143
4145}
#define CStringGetTextDatum(s)
Definition builtins.h:98
char * nodeToString(const void *obj)
Definition outfuncs.c:811
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
Definition partdesc.c:71
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition partdesc.c:501
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596

References Assert, CacheInvalidateRelcache(), CacheInvalidateRelcacheByRelid(), CatalogTupleUpdate(), CommandCounterIncrement(), CStringGetTextDatum, elog, ERROR, fb(), get_default_oid_from_partdesc(), GETSTRUCT(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, PartitionBoundSpec::is_default, nodeToString(), ObjectIdGetDatum(), OidIsValid, RelationData::rd_rel, RelationGetDescr, RelationGetPartitionDesc(), RelationGetRelid, RowExclusiveLock, SearchSysCacheCopy1, SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and update_default_partition_oid().

Referenced by attachPartitionTable(), and DefineRelation().

◆ StorePartitionKey()

void StorePartitionKey ( Relation  rel,
char  strategy,
int16  partnatts,
AttrNumber partattrs,
List partexprs,
Oid partopclass,
Oid partcollation 
)

Definition at line 3912 of file heap.c.

3919{
3920 int i;
3926 HeapTuple tuple;
3928 bool nulls[Natts_pg_partitioned_table] = {0};
3931 ObjectAddresses *addrs;
3932
3933 Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3934
3935 /* Copy the partition attribute numbers, opclass OIDs into arrays */
3936 partattrs_vec = buildint2vector(partattrs, partnatts);
3938 partcollation_vec = buildoidvector(partcollation, partnatts);
3939
3940 /* Convert the expressions (if any) to a text datum */
3941 if (partexprs)
3942 {
3943 char *exprString;
3944
3945 exprString = nodeToString(partexprs);
3948 }
3949 else
3950 partexprDatum = (Datum) 0;
3951
3953
3954 /* Only this can ever be NULL */
3955 if (!partexprDatum)
3956 nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3957
3966
3968
3971
3972 /* Mark this relation as dependent on a few things as follows */
3973 addrs = new_object_addresses();
3975
3976 /* Operator class and collation per key column */
3977 for (i = 0; i < partnatts; i++)
3978 {
3981
3982 /* The default collation is pinned, so don't bother recording it */
3983 if (OidIsValid(partcollation[i]) &&
3984 partcollation[i] != DEFAULT_COLLATION_OID)
3985 {
3988 }
3989 }
3990
3992 free_object_addresses(addrs);
3993
3994 /*
3995 * The partitioning columns are made internally dependent on the table,
3996 * because we cannot drop any of them without dropping the whole table.
3997 * (ATExecDropColumn independently enforces that, but it's not bulletproof
3998 * so we need the dependencies too.)
3999 */
4000 for (i = 0; i < partnatts; i++)
4001 {
4002 if (partattrs[i] == 0)
4003 continue; /* ignore expressions here */
4004
4006 RelationGetRelid(rel), partattrs[i]);
4008 }
4009
4010 /*
4011 * Also consider anything mentioned in partition expressions. External
4012 * references (e.g. functions) get NORMAL dependencies. Table columns
4013 * mentioned in the expressions are handled the same as plain partitioning
4014 * columns, i.e. they become internally dependent on the whole table.
4015 */
4016 if (partexprs)
4018 (Node *) partexprs,
4019 RelationGetRelid(rel),
4022 true /* reverse the self-deps */ );
4023
4024 /*
4025 * We must invalidate the relcache so that the next
4026 * CommandCounterIncrement() will cause the same to be rebuilt using the
4027 * information in just created catalog entry.
4028 */
4030}
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
@ DEPENDENCY_INTERNAL
Definition dependency.h:35
int2vector * buildint2vector(const int16 *int2s, int n)
Definition int.c:114
oidvector * buildoidvector(const Oid *oids, int n)
Definition oid.c:87
Definition c.h:815

References add_exact_object_address(), Assert, buildint2vector(), buildoidvector(), CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum(), CStringGetTextDatum, DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, fb(), free_object_addresses(), heap_form_tuple(), i, Int16GetDatum(), InvalidOid, new_object_addresses(), nodeToString(), ObjectAddressSet, ObjectAddressSubSet, ObjectIdGetDatum(), OidIsValid, pfree(), PointerGetDatum, RelationData::rd_rel, record_object_address_dependencies(), recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RelationGetRelid, RowExclusiveLock, table_close(), table_open(), and values.

Referenced by DefineRelation().

◆ StoreRelCheck()

static Oid StoreRelCheck ( Relation  rel,
const char ccname,
Node expr,
bool  is_enforced,
bool  is_validated,
bool  is_local,
int16  inhcount,
bool  is_no_inherit,
bool  is_internal 
)
static

Definition at line 2161 of file heap.c.

2164{
2165 char *ccbin;
2166 List *varList;
2167 int keycount;
2168 int16 *attNos;
2169 Oid constrOid;
2170
2171 /*
2172 * Flatten expression to string form for storage.
2173 */
2174 ccbin = nodeToString(expr);
2175
2176 /*
2177 * Find columns of rel that are used in expr
2178 *
2179 * NB: pull_var_clause is okay here only because we don't allow subselects
2180 * in check constraints; it would fail to examine the contents of
2181 * subselects.
2182 */
2183 varList = pull_var_clause(expr, 0);
2185
2186 if (keycount > 0)
2187 {
2188 ListCell *vl;
2189 int i = 0;
2190
2191 attNos = (int16 *) palloc(keycount * sizeof(int16));
2192 foreach(vl, varList)
2193 {
2194 Var *var = (Var *) lfirst(vl);
2195 int j;
2196
2197 for (j = 0; j < i; j++)
2198 if (attNos[j] == var->varattno)
2199 break;
2200 if (j == i)
2201 attNos[i++] = var->varattno;
2202 }
2203 keycount = i;
2204 }
2205 else
2206 attNos = NULL;
2207
2208 /*
2209 * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2210 * constraint makes no sense.
2211 */
2212 if (is_no_inherit &&
2213 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2214 ereport(ERROR,
2216 errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2218
2219 /*
2220 * Create the Check Constraint
2221 */
2222 constrOid =
2223 CreateConstraintEntry(ccname, /* Constraint Name */
2224 RelationGetNamespace(rel), /* namespace */
2225 CONSTRAINT_CHECK, /* Constraint Type */
2226 false, /* Is Deferrable */
2227 false, /* Is Deferred */
2228 is_enforced, /* Is Enforced */
2230 InvalidOid, /* no parent constraint */
2231 RelationGetRelid(rel), /* relation */
2232 attNos, /* attrs in the constraint */
2233 keycount, /* # key attrs in the constraint */
2234 keycount, /* # total attrs in the constraint */
2235 InvalidOid, /* not a domain constraint */
2236 InvalidOid, /* no associated index */
2237 InvalidOid, /* Foreign key fields */
2238 NULL,
2239 NULL,
2240 NULL,
2241 NULL,
2242 0,
2243 ' ',
2244 ' ',
2245 NULL,
2246 0,
2247 ' ',
2248 NULL, /* not an exclusion constraint */
2249 expr, /* Tree form of check constraint */
2250 ccbin, /* Binary form of check constraint */
2251 is_local, /* conislocal */
2252 inhcount, /* coninhcount */
2253 is_no_inherit, /* connoinherit */
2254 false, /* conperiod */
2255 is_internal); /* internally constructed? */
2256
2257 pfree(ccbin);
2258
2259 return constrOid;
2260}
void * palloc(Size size)
Definition mcxt.c:1387
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isEnforced, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int16 conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)

References CreateConstraintEntry(), ereport, errcode(), errmsg, ERROR, fb(), i, InvalidOid, j, lfirst, list_length(), nodeToString(), palloc(), pfree(), pull_var_clause(), RelationData::rd_rel, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, and Var::varattno.

Referenced by AddRelationNewConstraints(), and StoreConstraints().

◆ StoreRelNotNull()

static Oid StoreRelNotNull ( Relation  rel,
const char nnname,
AttrNumber  attnum,
bool  is_validated,
bool  is_local,
int  inhcount,
bool  is_no_inherit 
)
static

Definition at line 2268 of file heap.c.

2271{
2272 Oid constrOid;
2273
2275
2276 constrOid =
2280 false,
2281 false,
2282 true, /* Is Enforced */
2284 InvalidOid,
2285 RelationGetRelid(rel),
2286 &attnum,
2287 1,
2288 1,
2289 InvalidOid, /* not a domain constraint */
2290 InvalidOid, /* no associated index */
2291 InvalidOid, /* Foreign key fields */
2292 NULL,
2293 NULL,
2294 NULL,
2295 NULL,
2296 0,
2297 ' ',
2298 ' ',
2299 NULL,
2300 0,
2301 ' ',
2302 NULL, /* not an exclusion constraint */
2303 NULL,
2304 NULL,
2305 is_local,
2306 inhcount,
2307 is_no_inherit,
2308 false,
2309 false);
2310 return constrOid;
2311}

References Assert, attnum, CreateConstraintEntry(), fb(), InvalidAttrNumber, InvalidOid, RelationGetNamespace, and RelationGetRelid.

Referenced by AddRelationNewConstraints(), and AddRelationNotNullConstraints().

◆ SystemAttributeByName()

const FormData_pg_attribute * SystemAttributeByName ( const char attname)

Definition at line 248 of file heap.c.

249{
250 int j;
251
252 for (j = 0; j < (int) lengthof(SysAtt); j++)
253 {
254 const FormData_pg_attribute *att = SysAtt[j];
255
256 if (strcmp(NameStr(att->attname), attname) == 0)
257 return att;
258 }
259
260 return NULL;
261}

References attname, fb(), FormData_pg_attribute, j, lengthof, NameStr, and SysAtt.

Referenced by CheckAttributeNamesTypes(), expanded_record_lookup_field(), specialAttNum(), SPI_fnumber(), and transformIndexConstraint().

◆ SystemAttributeDefinition()

const FormData_pg_attribute * SystemAttributeDefinition ( AttrNumber  attno)

Definition at line 236 of file heap.c.

237{
238 if (attno >= 0 || attno < -(int) lengthof(SysAtt))
239 elog(ERROR, "invalid system attribute number %d", attno);
240 return SysAtt[-attno - 1];
241}

References elog, ERROR, lengthof, and SysAtt.

Referenced by attnumAttName(), attnumTypeId(), build_index_tlist(), scanNSItemForColumn(), SPI_fname(), SPI_gettype(), SPI_gettypeid(), SPI_getvalue(), and transformIndexConstraint().

Variable Documentation

◆ a1

Initial value:
= {
.attname = {"ctid"},
.atttypid = TIDOID,
.attlen = sizeof(ItemPointerData),
.atttypmod = -1,
.attbyval = false,
.attnotnull = true,
.attislocal = true,
}
char attstorage
bool attbyval
char attalign
bool attnotnull
#define SelfItemPointerAttributeNumber
Definition sysattr.h:21

Definition at line 144 of file heap.c.

144 {
145 .attname = {"ctid"},
146 .atttypid = TIDOID,
147 .attlen = sizeof(ItemPointerData),
149 .atttypmod = -1,
150 .attbyval = false,
153 .attnotnull = true,
154 .attislocal = true,
155};

Referenced by aclitem_eq(), aclitem_match(), aclitemComparator(), brin_minmax_multi_distance_float4(), brin_minmax_multi_distance_float8(), brin_minmax_multi_distance_int2(), brin_minmax_multi_distance_int4(), brin_minmax_multi_distance_int8(), brin_minmax_multi_distance_numeric(), brin_minmax_multi_distance_uuid(), build_distances(), cmpaffix(), deccall2(), deccall3(), distance_1D(), entryIndexByFrequencyCmp(), evalLazyFunc(), float8_qsort_cmp(), inet_merge(), inet_same_family(), int4gcd_internal(), int8gcd_internal(), macaddr8_cmp(), macaddr8_cmp_internal(), macaddr8_eq(), macaddr8_ge(), macaddr8_gt(), macaddr8_le(), macaddr8_lt(), macaddr8_ne(), macaddr_cmp(), macaddr_cmp_internal(), macaddr_eq(), macaddr_ge(), macaddr_gt(), macaddr_le(), macaddr_lt(), macaddr_ne(), MergeAffix(), network_cmp(), network_cmp_internal(), network_eq(), network_ge(), network_gt(), network_larger(), network_le(), network_lt(), network_ne(), network_overlap(), network_smaller(), network_sub(), network_subeq(), network_sup(), network_supeq(), packArcInfoCmp(), range_bound_qsort_cmp(), and sqrt_var().

◆ a2

Initial value:
= {
.attname = {"xmin"},
.atttypid = XIDOID,
.attlen = sizeof(TransactionId),
.atttypmod = -1,
.attbyval = true,
.attnotnull = true,
.attislocal = true,
}
#define MinTransactionIdAttributeNumber
Definition sysattr.h:22

Definition at line 157 of file heap.c.

157 {
158 .attname = {"xmin"},
159 .atttypid = XIDOID,
160 .attlen = sizeof(TransactionId),
162 .atttypmod = -1,
163 .attbyval = true,
166 .attnotnull = true,
167 .attislocal = true,
168};

Referenced by aclitem_eq(), aclitem_match(), aclitemComparator(), brin_minmax_multi_distance_float4(), brin_minmax_multi_distance_float8(), brin_minmax_multi_distance_int2(), brin_minmax_multi_distance_int4(), brin_minmax_multi_distance_int8(), brin_minmax_multi_distance_numeric(), brin_minmax_multi_distance_uuid(), build_distances(), clonesuccessorstates(), cmpaffix(), deccall2(), deccall3(), distance_1D(), entryIndexByFrequencyCmp(), evalLazyFunc(), float8_qsort_cmp(), inet_merge(), inet_same_family(), int4gcd_internal(), int8gcd_internal(), macaddr8_cmp(), macaddr8_cmp_internal(), macaddr8_eq(), macaddr8_ge(), macaddr8_gt(), macaddr8_le(), macaddr8_lt(), macaddr8_ne(), macaddr_cmp(), macaddr_cmp_internal(), macaddr_eq(), macaddr_ge(), macaddr_gt(), macaddr_le(), macaddr_lt(), macaddr_ne(), MergeAffix(), network_cmp(), network_cmp_internal(), network_eq(), network_ge(), network_gt(), network_larger(), network_le(), network_lt(), network_ne(), network_overlap(), network_smaller(), network_sub(), network_subeq(), network_sup(), network_supeq(), packArcInfoCmp(), and range_bound_qsort_cmp().

◆ a3

Initial value:
= {
.attname = {"cmin"},
.atttypid = CIDOID,
.attlen = sizeof(CommandId),
.atttypmod = -1,
.attbyval = true,
.attnotnull = true,
.attislocal = true,
}
uint32 CommandId
Definition c.h:750
#define MinCommandIdAttributeNumber
Definition sysattr.h:23

Definition at line 170 of file heap.c.

170 {
171 .attname = {"cmin"},
172 .atttypid = CIDOID,
173 .attlen = sizeof(CommandId),
175 .atttypmod = -1,
176 .attbyval = true,
179 .attnotnull = true,
180 .attislocal = true,
181};

◆ a4

Initial value:
= {
.attname = {"xmax"},
.atttypid = XIDOID,
.attlen = sizeof(TransactionId),
.atttypmod = -1,
.attbyval = true,
.attnotnull = true,
.attislocal = true,
}
#define MaxTransactionIdAttributeNumber
Definition sysattr.h:24

Definition at line 183 of file heap.c.

183 {
184 .attname = {"xmax"},
185 .atttypid = XIDOID,
186 .attlen = sizeof(TransactionId),
188 .atttypmod = -1,
189 .attbyval = true,
192 .attnotnull = true,
193 .attislocal = true,
194};

◆ a5

Initial value:
= {
.attname = {"cmax"},
.atttypid = CIDOID,
.attlen = sizeof(CommandId),
.atttypmod = -1,
.attbyval = true,
.attnotnull = true,
.attislocal = true,
}
#define MaxCommandIdAttributeNumber
Definition sysattr.h:25

Definition at line 196 of file heap.c.

196 {
197 .attname = {"cmax"},
198 .atttypid = CIDOID,
199 .attlen = sizeof(CommandId),
201 .atttypmod = -1,
202 .attbyval = true,
205 .attnotnull = true,
206 .attislocal = true,
207};

◆ a6

Initial value:
= {
.attname = {"tableoid"},
.atttypid = OIDOID,
.attlen = sizeof(Oid),
.atttypmod = -1,
.attbyval = true,
.attnotnull = true,
.attislocal = true,
}
#define TableOidAttributeNumber
Definition sysattr.h:26

Definition at line 215 of file heap.c.

215 {
216 .attname = {"tableoid"},
217 .atttypid = OIDOID,
218 .attlen = sizeof(Oid),
220 .atttypmod = -1,
221 .attbyval = true,
224 .attnotnull = true,
225 .attislocal = true,
226};

◆ binary_upgrade_next_heap_pg_class_oid

Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid

Definition at line 81 of file heap.c.

Referenced by binary_upgrade_set_next_heap_pg_class_oid(), and heap_create_with_catalog().

◆ binary_upgrade_next_heap_pg_class_relfilenumber

RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber = InvalidRelFileNumber

◆ binary_upgrade_next_toast_pg_class_oid

Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid

◆ binary_upgrade_next_toast_pg_class_relfilenumber

RelFileNumber binary_upgrade_next_toast_pg_class_relfilenumber = InvalidRelFileNumber

Definition at line 84 of file heap.c.

Referenced by binary_upgrade_set_next_toast_relfilenode(), and heap_create_with_catalog().

◆ SysAtt

const FormData_pg_attribute* const SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6}
static

Definition at line 228 of file heap.c.

228{&a1, &a2, &a3, &a4, &a5, &a6};
static const FormData_pg_attribute a4
Definition heap.c:183
static const FormData_pg_attribute a1
Definition heap.c:144
static const FormData_pg_attribute a6
Definition heap.c:215
static const FormData_pg_attribute a3
Definition heap.c:170
static const FormData_pg_attribute a2
Definition heap.c:157
static const FormData_pg_attribute a5
Definition heap.c:196

Referenced by AddNewAttributeTuples(), SystemAttributeByName(), and SystemAttributeDefinition().