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 849 of file heap.c.

852{
853 Relation rel;
855 int natts = tupdesc->natts;
858
859 /*
860 * open pg_attribute and its indexes.
861 */
863
865
867
868 /* add dependencies on their datatypes and collations */
869 for (int i = 0; i < natts; i++)
870 {
871 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
872
873 if (attr->attisdropped)
874 continue;
875
876 /* Add dependency info */
880
881 /* The default collation is pinned, so don't bother recording it */
882 if (OidIsValid(attr->attcollation) &&
883 attr->attcollation != DEFAULT_COLLATION_OID)
884 {
886 attr->attcollation);
888 }
889 }
890
891 /*
892 * Next we add the system attributes. Skip all for a view or type
893 * relation. We don't bother with making datatype dependencies here,
894 * since presumably all these types are pinned.
895 */
896 if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
897 {
898 TupleDesc td;
899
901
903 FreeTupleDesc(td);
904 }
905
906 /*
907 * clean up
908 */
910
912}
#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:732
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:51
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:569
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 1002 of file heap.c.

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

1068{
1069 return
1070 TypeCreate(new_row_type, /* optional predetermined OID */
1071 typeName, /* type name */
1072 typeNamespace, /* type namespace */
1073 new_rel_oid, /* relation oid */
1074 new_rel_kind, /* relation kind */
1075 ownerid, /* owner's ID */
1076 -1, /* internal size (varlena) */
1077 TYPTYPE_COMPOSITE, /* type-type (composite) */
1078 TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
1079 false, /* composite types are never preferred */
1080 DEFAULT_TYPDELIM, /* default array delimiter */
1081 F_RECORD_IN, /* input procedure */
1082 F_RECORD_OUT, /* output procedure */
1083 F_RECORD_RECV, /* receive procedure */
1084 F_RECORD_SEND, /* send procedure */
1085 InvalidOid, /* typmodin procedure - none */
1086 InvalidOid, /* typmodout procedure - none */
1087 InvalidOid, /* analyze procedure - default */
1088 InvalidOid, /* subscript procedure - none */
1089 InvalidOid, /* array element type - irrelevant */
1090 false, /* this is not an array type */
1091 new_array_type, /* array type if any */
1092 InvalidOid, /* domain base type - irrelevant */
1093 NULL, /* default value - none */
1094 NULL, /* default binary representation */
1095 false, /* passed by reference */
1096 TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1097 TYPSTORAGE_EXTENDED, /* fully TOASTable */
1098 -1, /* typmod */
1099 0, /* array dimensions for typBaseType */
1100 false, /* Type NOT NULL */
1101 InvalidOid); /* rowtypes never have a collation */
1102}
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 2405 of file heap.c.

2412{
2416 int numoldchecks;
2417 ParseState *pstate;
2419 int numchecks;
2421 List *nnnames;
2422 Node *expr;
2424
2425 /*
2426 * Get info about existing constraints.
2427 */
2429 oldconstr = tupleDesc->constr;
2430 if (oldconstr)
2431 numoldchecks = oldconstr->num_check;
2432 else
2433 numoldchecks = 0;
2434
2435 /*
2436 * Create a dummy ParseState and insert the target relation as its sole
2437 * rangetable entry. We need a ParseState for transformExpr.
2438 */
2439 pstate = make_parsestate(NULL);
2440 pstate->p_sourcetext = queryString;
2442 rel,
2444 NULL,
2445 false,
2446 true);
2447 addNSItemToQuery(pstate, nsitem, true, true, true);
2448
2449 /*
2450 * Process column default expressions.
2451 */
2453 {
2454 Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2455 Oid defOid;
2456
2457 expr = cookDefault(pstate, colDef->raw_default,
2458 atp->atttypid, atp->atttypmod,
2459 NameStr(atp->attname),
2460 atp->attgenerated);
2461
2462 /*
2463 * If the expression is just a NULL constant, we do not bother to make
2464 * an explicit pg_attrdef entry, since the default behavior is
2465 * equivalent. This applies to column defaults, but not for
2466 * generation expressions.
2467 *
2468 * Note a nonobvious property of this test: if the column is of a
2469 * domain type, what we'll get is not a bare null Const but a
2470 * CoerceToDomain expr, so we will not discard the default. This is
2471 * critical because the column default needs to be retained to
2472 * override any default that the domain might have.
2473 */
2474 if (expr == NULL ||
2475 (!colDef->generated &&
2476 IsA(expr, Const) &&
2477 castNode(Const, expr)->constisnull))
2478 continue;
2479
2480 defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
2481
2483 cooked->contype = CONSTR_DEFAULT;
2484 cooked->conoid = defOid;
2485 cooked->name = NULL;
2486 cooked->attnum = colDef->attnum;
2487 cooked->expr = expr;
2488 cooked->is_enforced = true;
2489 cooked->skip_validation = false;
2490 cooked->is_local = is_local;
2491 cooked->inhcount = is_local ? 0 : 1;
2492 cooked->is_no_inherit = false;
2494 }
2495
2496 /*
2497 * Process constraint expressions.
2498 */
2500 checknames = NIL;
2501 nnnames = NIL;
2503 {
2504 Oid constrOid;
2505
2506 if (cdef->contype == CONSTR_CHECK)
2507 {
2508 char *ccname;
2509
2510 if (cdef->raw_expr != NULL)
2511 {
2512 Assert(cdef->cooked_expr == NULL);
2513
2514 /*
2515 * Transform raw parsetree to executable expression, and
2516 * verify it's valid as a CHECK constraint.
2517 */
2518 expr = cookConstraint(pstate, cdef->raw_expr,
2520 }
2521 else
2522 {
2523 Assert(cdef->cooked_expr != NULL);
2524
2525 /*
2526 * Here, we assume the parser will only pass us valid CHECK
2527 * expressions, so we do no particular checking.
2528 */
2529 expr = stringToNode(cdef->cooked_expr);
2530 }
2531
2532 /*
2533 * Check name uniqueness, or generate a name if none was given.
2534 */
2535 if (cdef->conname != NULL)
2536 {
2537 ccname = cdef->conname;
2538 /* Check against other new constraints */
2539 /* Needed because we don't do CommandCounterIncrement in loop */
2541 {
2542 if (strcmp(chkname, ccname) == 0)
2543 ereport(ERROR,
2545 errmsg("check constraint \"%s\" already exists",
2546 ccname)));
2547 }
2548
2549 /* save name for future checks */
2550 checknames = lappend(checknames, ccname);
2551
2552 /*
2553 * Check against pre-existing constraints. If we are allowed
2554 * to merge with an existing constraint, there's no more to do
2555 * here. (We omit the duplicate constraint from the result,
2556 * which is what ATAddCheckNNConstraint wants.)
2557 */
2558 if (MergeWithExistingConstraint(rel, ccname, expr,
2559 allow_merge, is_local,
2560 cdef->is_enforced,
2561 cdef->initially_valid,
2562 cdef->is_no_inherit))
2563 continue;
2564 }
2565 else
2566 {
2567 /*
2568 * When generating a name, we want to create "tab_col_check"
2569 * for a column constraint and "tab_check" for a table
2570 * constraint. We no longer have any info about the syntactic
2571 * positioning of the constraint phrase, so we approximate
2572 * this by seeing whether the expression references more than
2573 * one column. (If the user played by the rules, the result
2574 * is the same...)
2575 *
2576 * Note: pull_var_clause() doesn't descend into sublinks, but
2577 * we eliminated those above; and anyway this only needs to be
2578 * an approximate answer.
2579 */
2580 List *vars;
2581 char *colname;
2582
2583 vars = pull_var_clause(expr, 0);
2584
2585 /* eliminate duplicates */
2586 vars = list_union(NIL, vars);
2587
2588 if (list_length(vars) == 1)
2589 colname = get_attname(RelationGetRelid(rel),
2590 ((Var *) linitial(vars))->varattno,
2591 true);
2592 else
2593 colname = NULL;
2594
2596 colname,
2597 "check",
2599 checknames);
2600
2601 /* save name for future checks */
2602 checknames = lappend(checknames, ccname);
2603 }
2604
2605 /*
2606 * OK, store it.
2607 */
2608 constrOid =
2609 StoreRelCheck(rel, ccname, expr, cdef->is_enforced,
2610 cdef->initially_valid, is_local,
2611 is_local ? 0 : 1, cdef->is_no_inherit,
2612 is_internal);
2613
2614 numchecks++;
2615
2617 cooked->contype = CONSTR_CHECK;
2618 cooked->conoid = constrOid;
2619 cooked->name = ccname;
2620 cooked->attnum = 0;
2621 cooked->expr = expr;
2622 cooked->is_enforced = cdef->is_enforced;
2623 cooked->skip_validation = cdef->skip_validation;
2624 cooked->is_local = is_local;
2625 cooked->inhcount = is_local ? 0 : 1;
2626 cooked->is_no_inherit = cdef->is_no_inherit;
2628 }
2629 else if (cdef->contype == CONSTR_NOTNULL)
2630 {
2632 AttrNumber colnum;
2633 int16 inhcount = is_local ? 0 : 1;
2634 char *nnname;
2635
2636 /* Determine which column to modify */
2637 colnum = get_attnum(RelationGetRelid(rel), strVal(linitial(cdef->keys)));
2638 if (colnum == InvalidAttrNumber)
2639 ereport(ERROR,
2641 errmsg("column \"%s\" of relation \"%s\" does not exist",
2643 if (colnum < InvalidAttrNumber)
2644 ereport(ERROR,
2646 errmsg("cannot add not-null constraint on system column \"%s\"",
2647 strVal(linitial(cdef->keys))));
2648
2649 Assert(cdef->initially_valid != cdef->skip_validation);
2650
2651 /*
2652 * If the column already has a not-null constraint, we don't want
2653 * to add another one; adjust inheritance status as needed. This
2654 * also checks whether the existing constraint matches the
2655 * requested validity.
2656 */
2658 cdef->conname,
2659 is_local, cdef->is_no_inherit,
2660 cdef->skip_validation))
2661 continue;
2662
2663 /*
2664 * If a constraint name is specified, check that it isn't already
2665 * used. Otherwise, choose a non-conflicting one ourselves.
2666 */
2667 if (cdef->conname)
2668 {
2670 RelationGetRelid(rel),
2671 cdef->conname))
2672 ereport(ERROR,
2674 errmsg("constraint \"%s\" for relation \"%s\" already exists",
2675 cdef->conname, RelationGetRelationName(rel)));
2676 nnname = cdef->conname;
2677 }
2678 else
2680 strVal(linitial(cdef->keys)),
2681 "not_null",
2683 nnnames);
2685
2686 constrOid =
2687 StoreRelNotNull(rel, nnname, colnum,
2688 cdef->initially_valid,
2689 is_local,
2690 inhcount,
2691 cdef->is_no_inherit);
2692
2694 nncooked->contype = CONSTR_NOTNULL;
2695 nncooked->conoid = constrOid;
2696 nncooked->name = nnname;
2697 nncooked->attnum = colnum;
2698 nncooked->expr = NULL;
2699 nncooked->is_enforced = true;
2700 nncooked->skip_validation = cdef->skip_validation;
2701 nncooked->is_local = is_local;
2702 nncooked->inhcount = inhcount;
2703 nncooked->is_no_inherit = cdef->is_no_inherit;
2704
2706 }
2707 }
2708
2709 /*
2710 * Update the count of constraints in the relation's pg_class tuple. We do
2711 * this even if there was no change, in order to ensure that an SI update
2712 * message is sent out for the pg_class tuple, which will force other
2713 * backends to rebuild their relcache entries for the rel. (This is
2714 * critical if we added defaults but not constraints.)
2715 */
2717
2718 return cookedConstraints;
2719}
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:89
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:2167
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:2732
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:2274
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition heap.c:3169
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
Definition heap.c:3343
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition heap.c:3424
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:1076
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1045
#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 2917 of file heap.c.

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

3246{
3247 check_nested_generated_walker(node, pstate);
3248}
static bool check_nested_generated_walker(Node *node, void *context)
Definition heap.c:3203

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 3203 of file heap.c.

3204{
3205 ParseState *pstate = context;
3206
3207 if (node == NULL)
3208 return false;
3209 else if (IsA(node, Var))
3210 {
3211 Var *var = (Var *) node;
3212 Oid relid;
3214
3215 relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
3216 if (!OidIsValid(relid))
3217 return false; /* XXX shouldn't we raise an error? */
3218
3219 attnum = var->varattno;
3220
3221 if (attnum > 0 && get_attgenerated(relid, attnum))
3222 ereport(ERROR,
3224 errmsg("cannot use generated column \"%s\" in column generation expression",
3225 get_attname(relid, attnum, false)),
3226 errdetail("A generated column cannot reference another generated column."),
3227 parser_errposition(pstate, var->location)));
3228 /* A whole-row Var is necessarily self-referential, so forbid it */
3229 if (attnum == 0)
3230 ereport(ERROR,
3232 errmsg("cannot use whole-row variable in column generation expression"),
3233 errdetail("This would cause the generated column to depend on its own value."),
3234 parser_errposition(pstate, var->location)));
3235 /* System columns were already checked in the parser */
3236
3237 return false;
3238 }
3239 else
3241 context);
3242}
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1106
#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 3325 of file heap.c.

3326{
3328}
static bool check_virtual_generated_security_walker(Node *node, void *context)
Definition heap.c:3288

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 3288 of file heap.c.

3289{
3290 ParseState *pstate = context;
3291
3292 if (node == NULL)
3293 return false;
3294
3295 if (!IsA(node, List))
3296 {
3298 ereport(ERROR,
3300 errmsg("generation expression uses user-defined function"),
3301 errdetail("Virtual generated columns that make use of user-defined functions are not yet supported."),
3302 parser_errposition(pstate, exprLocation(node)));
3303
3304 /*
3305 * check_functions_in_node() doesn't check some node types (see
3306 * comment there). We handle CoerceToDomain and MinMaxExpr by
3307 * checking for built-in types. The other listed node types cannot
3308 * call user-definable SQL-visible functions.
3309 *
3310 * We furthermore need this type check to handle built-in, immutable
3311 * polymorphic functions such as array_eq().
3312 */
3313 if (exprType(node) >= FirstUnpinnedObjectId)
3314 ereport(ERROR,
3316 errmsg("generation expression uses user-defined type"),
3317 errdetail("Virtual generated columns that make use of user-defined types are not yet supported."),
3318 parser_errposition(pstate, exprLocation(node)));
3319 }
3320
3322}
static bool contains_user_functions_checker(Oid func_id, void *context)
Definition heap.c:3277
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:1928
int exprLocation(const Node *expr)
Definition nodeFuncs.c:1403
#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 453 of file heap.c.

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

553{
556
557 /* since this function recurses, it could be driven to stack overflow */
559
561 {
562 /*
563 * We disallow pseudo-type columns, with the exception of ANYARRAY,
564 * RECORD, and RECORD[] when the caller says that those are OK.
565 *
566 * We don't need to worry about recursive containment for RECORD and
567 * RECORD[] because (a) no named composite type should be allowed to
568 * contain those, and (b) two "anonymous" record types couldn't be
569 * considered to be the same type, so infinite recursion isn't
570 * possible.
571 */
572 if (!((atttypid == ANYARRAYOID && (flags & CHKATYPE_ANYARRAY)) ||
573 (atttypid == RECORDOID && (flags & CHKATYPE_ANYRECORD)) ||
574 (atttypid == RECORDARRAYOID && (flags & CHKATYPE_ANYRECORD))))
575 {
576 if (flags & CHKATYPE_IS_PARTKEY)
579 /* translator: first %s is an integer not a name */
580 errmsg("partition key column %s has pseudo-type %s",
582 else
585 errmsg("column \"%s\" has pseudo-type %s",
587 }
588 }
589 else if (att_typtype == TYPTYPE_DOMAIN)
590 {
591 /*
592 * Prevent virtual generated columns from having a domain type. We
593 * would have to enforce domain constraints when columns underlying
594 * the generated column change. This could possibly be implemented,
595 * but it's not.
596 */
597 if (flags & CHKATYPE_IS_VIRTUAL)
600 errmsg("virtual generated column \"%s\" cannot have a domain type", attname));
601
602 /*
603 * If it's a domain, recurse to check its base type.
604 */
607 flags);
608 }
609 else if (att_typtype == TYPTYPE_COMPOSITE)
610 {
611 /*
612 * For a composite type, recurse into its attributes.
613 */
614 Relation relation;
615 TupleDesc tupdesc;
616 int i;
617
618 /*
619 * Check for self-containment. Eventually we might be able to allow
620 * this (just return without complaint, if so) but it's not clear how
621 * many other places would require anti-recursion defenses before it
622 * would be safe to allow tables to contain their own rowtype.
623 */
627 errmsg("composite type %s cannot be made a member of itself",
629
631
633
634 tupdesc = RelationGetDescr(relation);
635
636 for (i = 0; i < tupdesc->natts; i++)
637 {
638 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
639
640 if (attr->attisdropped)
641 continue;
642 CheckAttributeType(NameStr(attr->attname),
643 attr->atttypid, attr->attcollation,
645 flags & ~CHKATYPE_IS_PARTKEY);
646 }
647
649
651 }
652 else if (att_typtype == TYPTYPE_RANGE)
653 {
654 /*
655 * If it's a range, recurse to check its subtype.
656 */
660 flags);
661 }
663 {
664 /*
665 * If it's a multirange, recurse to check its plain range type.
666 */
668 InvalidOid, /* range types are not collatable */
670 flags);
671 }
673 {
674 /*
675 * Must recurse into array types, too, in case they are composite.
676 */
679 flags);
680 }
681
682 /*
683 * For consistency with check_virtual_generated_security().
684 */
688 errmsg("virtual generated column \"%s\" cannot have a user-defined type", attname),
689 errdetail("Virtual generated columns that make use of user-defined types are not yet supported."));
690
691 /*
692 * This might not be strictly invalid per SQL standard, but it is pretty
693 * useless, and it cannot be dumped, so we must disallow it.
694 */
695 if (!OidIsValid(attcollation) && type_is_collatable(atttypid))
696 {
697 if (flags & CHKATYPE_IS_PARTKEY)
700 /* translator: first %s is an integer not a name */
701 errmsg("no collation was derived for partition key column %s with collatable type %s",
703 errhint("Use the COLLATE clause to set the collation explicitly.")));
704 else
707 errmsg("no collation was derived for column \"%s\" with collatable type %s",
709 errhint("Use the COLLATE clause to set the collation explicitly.")));
710 }
711}
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:3735
Oid get_element_type(Oid typid)
Definition lsyscache.c:3067
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3836
Oid get_range_collation(Oid rangeOid)
Definition lsyscache.c:3761
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3389
Oid get_typ_typrelid(Oid typid)
Definition lsyscache.c:3039
char get_typtype(Oid typid)
Definition lsyscache.c:2937
Oid getBaseType(Oid typid)
Definition lsyscache.c:2829
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:96

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 3277 of file heap.c.

3278{
3279 return (func_id >= FirstUnpinnedObjectId);
3280}

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 3424 of file heap.c.

3427{
3428 Node *expr;
3429
3430 /*
3431 * Transform raw parsetree to executable expression.
3432 */
3434
3435 /*
3436 * Make sure it yields a boolean result.
3437 */
3438 expr = coerce_to_boolean(pstate, expr, "CHECK");
3439
3440 /*
3441 * Take care of collations.
3442 */
3443 assign_expr_collations(pstate, expr);
3444
3445 /*
3446 * Make sure no outside relations are referred to (this is probably dead
3447 * code now that add_missing_from is history).
3448 */
3449 if (list_length(pstate->p_rtable) != 1)
3450 ereport(ERROR,
3452 errmsg("only table \"%s\" can be referenced in check constraint",
3453 relname)));
3454
3455 return expr;
3456}
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 3343 of file heap.c.

3349{
3350 Node *expr;
3351
3352 Assert(raw_default != NULL);
3353
3354 /*
3355 * Transform raw parsetree to executable expression.
3356 */
3357 expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
3358
3359 if (attgenerated)
3360 {
3361 /* Disallow refs to other generated columns */
3362 check_nested_generated(pstate, expr);
3363
3364 /* Disallow mutable functions */
3366 ereport(ERROR,
3368 errmsg("generation expression is not immutable")));
3369
3370 /* Check security of expressions for virtual generated column */
3371 if (attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
3373 }
3374 else
3375 {
3376 /*
3377 * For a default expression, transformExpr() should have rejected
3378 * column references.
3379 */
3380 Assert(!contain_var_clause(expr));
3381 }
3382
3383 /*
3384 * Coerce the expression to the correct type and typmod, if given. This
3385 * should match the parser's processing of non-defaulted expressions ---
3386 * see transformAssignedExpr().
3387 */
3388 if (OidIsValid(atttypid))
3389 {
3390 Oid type_id = exprType(expr);
3391
3392 expr = coerce_to_target_type(pstate, expr, type_id,
3393 atttypid, atttypmod,
3396 -1);
3397 if (expr == NULL)
3398 ereport(ERROR,
3400 errmsg("column \"%s\" is of type %s"
3401 " but default expression is of type %s",
3402 attname,
3404 format_type_be(type_id)),
3405 errhint("You will need to rewrite or cast the expression.")));
3406 }
3407
3408 /*
3409 * Finally, take care of collations in the finished expression.
3410 */
3411 assign_expr_collations(pstate, expr);
3412
3413 return expr;
3414}
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:3325
static void check_nested_generated(ParseState *pstate, Node *node)
Definition heap.c:3245
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 3462 of file heap.c.

3463{
3464 HeapTuple tup;
3465 SysScanDesc scan;
3466 ScanKeyData key[1];
3469
3471
3472 /* Now search for stat records */
3473 ScanKeyInit(&key[0],
3477
3479 true, NULL, 1, key);
3480
3481 while (HeapTupleIsValid((tup = systable_getnext(scan))))
3482 {
3484
3485 /* make a modifiable copy */
3488
3489 /* update the copy of the tuple and insert it */
3490 statform->starelid = torelid;
3491
3492 /* fetch index information when we know we need it */
3493 if (indstate == NULL)
3495
3497
3499 }
3500
3501 systable_endscan(scan);
3502
3503 if (indstate != NULL)
3506}
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:515
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 1625 of file heap.c.

1626{
1628 SysScanDesc scan;
1629 ScanKeyData key[1];
1631
1632 /* Grab an appropriate lock on the pg_attribute relation */
1634
1635 /* Use the index to scan only attributes of the target relation */
1636 ScanKeyInit(&key[0],
1639 ObjectIdGetDatum(relid));
1640
1642 NULL, 1, key);
1643
1644 /* Delete all the matching tuples */
1645 while ((atttup = systable_getnext(scan)) != NULL)
1646 CatalogTupleDelete(attrel, &atttup->t_self);
1647
1648 /* Clean up after the scan */
1649 systable_endscan(scan);
1651}
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 1596 of file heap.c.

1597{
1599 HeapTuple tup;
1600
1601 /* Grab an appropriate lock on the pg_class relation */
1603
1605 if (!HeapTupleIsValid(tup))
1606 elog(ERROR, "cache lookup failed for relation %u", relid);
1607
1608 /* delete the relation tuple from pg_class, and finish up */
1610
1612
1614}
#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 1662 of file heap.c.

1663{
1665 SysScanDesc scan;
1666 ScanKeyData key[2];
1668
1669 /* Grab an appropriate lock on the pg_attribute relation */
1671
1672 /* Use the index to scan only system attributes of the target relation */
1673 ScanKeyInit(&key[0],
1676 ObjectIdGetDatum(relid));
1677 ScanKeyInit(&key[1],
1680 Int16GetDatum(0));
1681
1683 NULL, 2, key);
1684
1685 /* Delete all the matching tuples */
1686 while ((atttup = systable_getnext(scan)) != NULL)
1687 CatalogTupleDelete(attrel, &atttup->t_self);
1688
1689 /* Clean up after the scan */
1690 systable_endscan(scan);
1692}
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 286 of file heap.c.

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

1161{
1164 Acl *relacl;
1168
1169 /* By default set to InvalidOid unless overridden by binary-upgrade */
1170 RelFileNumber relfilenumber = InvalidRelFileNumber;
1171 TransactionId relfrozenxid;
1172 MultiXactId relminmxid;
1173
1175
1176 /*
1177 * sanity checks
1178 */
1180
1181 /*
1182 * Validate proposed tupdesc for the desired relkind. If
1183 * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
1184 * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
1185 */
1186 CheckAttributeNamesTypes(tupdesc, relkind,
1188
1189 /*
1190 * This would fail later on anyway, if the relation already exists. But
1191 * by catching it here we can emit a nicer error message.
1192 */
1193 existing_relid = get_relname_relid(relname, relnamespace);
1195 ereport(ERROR,
1197 errmsg("relation \"%s\" already exists", relname)));
1198
1199 /*
1200 * Since we are going to create a rowtype as well, also check for
1201 * collision with an existing type name. If there is one and it's an
1202 * autogenerated array, we can rename it out of the way; otherwise we can
1203 * at least give a good error message.
1204 */
1207 ObjectIdGetDatum(relnamespace));
1209 {
1210 if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
1211 ereport(ERROR,
1213 errmsg("type \"%s\" already exists", relname),
1214 errhint("A relation has an associated type of the same name, "
1215 "so you must use a name that doesn't conflict "
1216 "with any existing type.")));
1217 }
1218
1219 /*
1220 * Shared relations must be in pg_global (last-ditch check)
1221 */
1222 if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
1223 elog(ERROR, "shared relations must be placed in pg_global tablespace");
1224
1225 /*
1226 * Allocate an OID for the relation, unless we were told what to use.
1227 *
1228 * The OID will be the relfilenumber as well, so make sure it doesn't
1229 * collide with either pg_class OIDs or existing physical files.
1230 */
1231 if (!OidIsValid(relid))
1232 {
1233 /* Use binary-upgrade override for pg_class.oid and relfilenumber */
1234 if (IsBinaryUpgrade)
1235 {
1236 /*
1237 * Indexes are not supported here; they use
1238 * binary_upgrade_next_index_pg_class_oid.
1239 */
1240 Assert(relkind != RELKIND_INDEX);
1242
1243 if (relkind == RELKIND_TOASTVALUE)
1244 {
1245 /* There might be no TOAST table, so we have to test for it. */
1247 {
1250
1252 ereport(ERROR,
1254 errmsg("toast relfilenumber value not set when in binary upgrade mode")));
1255
1258 }
1259 }
1260 else
1261 {
1263 ereport(ERROR,
1265 errmsg("pg_class heap OID value not set when in binary upgrade mode")));
1266
1269
1270 if (RELKIND_HAS_STORAGE(relkind))
1271 {
1273 ereport(ERROR,
1275 errmsg("relfilenumber value not set when in binary upgrade mode")));
1276
1279 }
1280 }
1281 }
1282
1283 if (!OidIsValid(relid))
1284 relid = GetNewRelFileNumber(reltablespace, pg_class_desc,
1285 relpersistence);
1286 }
1287
1288 /*
1289 * Other sessions' catalog scans can't find this until we commit. Hence,
1290 * it doesn't hurt to hold AccessExclusiveLock. Do it here so callers
1291 * can't accidentally vary in their lock mode or acquisition timing.
1292 */
1294
1295 /*
1296 * Determine the relation's initial permissions.
1297 */
1298 if (use_user_acl)
1299 {
1300 switch (relkind)
1301 {
1302 case RELKIND_RELATION:
1303 case RELKIND_VIEW:
1304 case RELKIND_MATVIEW:
1308 relnamespace);
1309 break;
1310 case RELKIND_SEQUENCE:
1312 relnamespace);
1313 break;
1314 default:
1315 relacl = NULL;
1316 break;
1317 }
1318 }
1319 else
1320 relacl = NULL;
1321
1322 /*
1323 * Create the relcache entry (mostly dummy at this point) and the physical
1324 * disk file. (If we fail further down, it's the smgr's responsibility to
1325 * remove the disk file again.)
1326 *
1327 * NB: Note that passing create_storage = true is correct even for binary
1328 * upgrade. The storage we create here will be replaced later, but we
1329 * need to have something on disk in the meanwhile.
1330 */
1332 relnamespace,
1333 reltablespace,
1334 relid,
1335 relfilenumber,
1336 accessmtd,
1337 tupdesc,
1338 relkind,
1339 relpersistence,
1343 &relfrozenxid,
1344 &relminmxid,
1345 true);
1346
1348
1349 new_rel_desc->rd_rel->relrewrite = relrewrite;
1350
1351 /*
1352 * Decide whether to create a pg_type entry for the relation's rowtype.
1353 * These types are made except where the use of a relation as such is an
1354 * implementation detail: toast tables, sequences, indexes, and property
1355 * graphs.
1356 */
1357 if (!(relkind == RELKIND_SEQUENCE ||
1358 relkind == RELKIND_TOASTVALUE ||
1359 relkind == RELKIND_INDEX ||
1360 relkind == RELKIND_PARTITIONED_INDEX ||
1361 relkind == RELKIND_PROPGRAPH))
1362 {
1365 char *relarrayname;
1366
1367 /*
1368 * We'll make an array over the composite type, too. For largely
1369 * historical reasons, the array type's OID is assigned first.
1370 */
1372
1373 /*
1374 * Make the pg_type entry for the composite type. The OID of the
1375 * composite type can be preselected by the caller, but if reltypeid
1376 * is InvalidOid, we'll generate a new OID for it.
1377 *
1378 * NOTE: we could get a unique-index failure here, in case someone
1379 * else is creating the same type name in parallel but hadn't
1380 * committed yet when we checked for a duplicate name above.
1381 */
1383 relnamespace,
1384 relid,
1385 relkind,
1386 ownerid,
1387 reltypeid,
1389 new_type_oid = new_type_addr.objectId;
1390 if (typaddress)
1392
1393 /* Now create the array type. */
1394 relarrayname = makeArrayTypeName(relname, relnamespace);
1395
1396 TypeCreate(new_array_oid, /* force the type's OID to this */
1397 relarrayname, /* Array type name */
1398 relnamespace, /* Same namespace as parent */
1399 InvalidOid, /* Not composite, no relationOid */
1400 0, /* relkind, also N/A here */
1401 ownerid, /* owner's ID */
1402 -1, /* Internal size (varlena) */
1403 TYPTYPE_BASE, /* Not composite - typelem is */
1404 TYPCATEGORY_ARRAY, /* type-category (array) */
1405 false, /* array types are never preferred */
1406 DEFAULT_TYPDELIM, /* default array delimiter */
1407 F_ARRAY_IN, /* array input proc */
1408 F_ARRAY_OUT, /* array output proc */
1409 F_ARRAY_RECV, /* array recv (bin) proc */
1410 F_ARRAY_SEND, /* array send (bin) proc */
1411 InvalidOid, /* typmodin procedure - none */
1412 InvalidOid, /* typmodout procedure - none */
1413 F_ARRAY_TYPANALYZE, /* array analyze procedure */
1414 F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
1415 new_type_oid, /* array element type - the rowtype */
1416 true, /* yes, this is an array type */
1417 InvalidOid, /* this has no array type */
1418 InvalidOid, /* domain base type - irrelevant */
1419 NULL, /* default value - none */
1420 NULL, /* default binary representation */
1421 false, /* passed by reference */
1422 TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1423 TYPSTORAGE_EXTENDED, /* fully TOASTable */
1424 -1, /* typmod */
1425 0, /* array dimensions for typBaseType */
1426 false, /* Type NOT NULL */
1427 InvalidOid); /* rowtypes never have a collation */
1428
1430 }
1431 else
1432 {
1433 /* Caller should not be expecting a type to be created. */
1436
1438 }
1439
1440 /*
1441 * now create an entry in pg_class for the relation.
1442 *
1443 * NOTE: we could get a unique-index failure here, in case someone else is
1444 * creating the same relation name in parallel but hadn't committed yet
1445 * when we checked for a duplicate name above.
1446 */
1449 relid,
1452 ownerid,
1453 relkind,
1454 relfrozenxid,
1455 relminmxid,
1457 reloptions);
1458
1459 /*
1460 * now add tuples to pg_attribute for the attributes in our new relation.
1461 */
1462 AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
1463
1464 /*
1465 * Make a dependency link to force the relation to be deleted if its
1466 * namespace is. Also make a dependency link to its owner, as well as
1467 * dependencies for any roles mentioned in the default ACL.
1468 *
1469 * For composite types, these dependencies are tracked for the pg_type
1470 * entry, so we needn't record them here. Likewise, TOAST tables don't
1471 * need a namespace dependency (they live in a pinned namespace) nor an
1472 * owner dependency (they depend indirectly through the parent table), nor
1473 * should they have any ACL entries. The same applies for extension
1474 * dependencies.
1475 *
1476 * Also, skip this in bootstrap mode, since we don't make dependencies
1477 * while bootstrapping.
1478 */
1479 if (relkind != RELKIND_COMPOSITE_TYPE &&
1480 relkind != RELKIND_TOASTVALUE &&
1482 {
1484 referenced;
1485 ObjectAddresses *addrs;
1486
1488
1490
1492
1494
1495 addrs = new_object_addresses();
1496
1499
1500 if (reloftypeid)
1501 {
1504 }
1505
1506 /*
1507 * Make a dependency link to force the relation to be deleted if its
1508 * access method is.
1509 *
1510 * No need to add an explicit dependency for the toast table, as the
1511 * main table depends on it. Partitioned tables may not have an
1512 * access method set.
1513 */
1514 if ((RELKIND_HAS_TABLE_AM(relkind) && relkind != RELKIND_TOASTVALUE) ||
1516 {
1519 }
1520
1522 free_object_addresses(addrs);
1523 }
1524
1525 /* Post creation hook for new relation */
1526 InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
1527
1528 /*
1529 * Store any supplied CHECK constraints and defaults.
1530 *
1531 * NB: this may do a CommandCounterIncrement and rebuild the relcache
1532 * entry, so the relation must be valid and self-consistent at this point.
1533 * In particular, there are not yet constraints and defaults anywhere.
1534 */
1536
1537 /*
1538 * If there's a special on-commit action, remember it
1539 */
1540 if (oncommit != ONCOMMIT_NOOP)
1541 register_on_commit_action(relid, oncommit);
1542
1543 /*
1544 * ok, the relation has been cataloged, so close our relations and return
1545 * the OID of the newly created relation.
1546 */
1547 table_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
1549
1550 return relid;
1551}
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition aclchk.c:4371
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition aclchk.c:4291
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:2330
static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, char relkind)
Definition heap.c:849
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:1002
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:1061
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, int flags)
Definition heap.c:453
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:286
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:2191
void pfree(void *pointer)
Definition mcxt.c:1619
#define IsBootstrapProcessingMode()
Definition miscadmin.h:486
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
@ OBJECT_SEQUENCE
@ OBJECT_TABLE
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition pg_depend.c:206
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:2480

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 1804 of file heap.c.

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

3612{
3613 List *relations = NIL;
3614 ListCell *cell;
3615
3616 /* Open relations for processing, and grab exclusive access on each */
3617 foreach(cell, relids)
3618 {
3619 Oid rid = lfirst_oid(cell);
3620 Relation rel;
3621
3622 rel = table_open(rid, AccessExclusiveLock);
3623 relations = lappend(relations, rel);
3624 }
3625
3626 /* Don't allow truncate on tables that are referenced by foreign keys */
3627 heap_truncate_check_FKs(relations, true);
3628
3629 /* OK to do it */
3630 foreach(cell, relations)
3631 {
3632 Relation rel = lfirst(cell);
3633
3634 /* Truncate the relation */
3636
3637 /* Close the relation, but keep exclusive lock on it until commit */
3638 table_close(rel, NoLock);
3639 }
3640}
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition heap.c:3696
void heap_truncate_one_rel(Relation rel)
Definition heap.c:3652
#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 3696 of file heap.c.

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

3792{
3793 List *result = NIL;
3794 List *oids;
3796 ListCell *cell;
3800 HeapTuple tuple;
3801 bool restart;
3802
3803 oids = list_copy(relationIds);
3804
3805 /*
3806 * Must scan pg_constraint. Right now, it is a seqscan because there is
3807 * no available index on confrelid.
3808 */
3810
3811restart:
3812 restart = false;
3813 parent_cons = NIL;
3814
3816 NULL, 0, NULL);
3817
3819 {
3821
3822 /* Not a foreign key */
3823 if (con->contype != CONSTRAINT_FOREIGN)
3824 continue;
3825
3826 /* Not referencing one of our list of tables */
3827 if (!list_member_oid(oids, con->confrelid))
3828 continue;
3829
3830 /*
3831 * If this constraint has a parent constraint which we have not seen
3832 * yet, keep track of it for the second loop, below. Tracking parent
3833 * constraints allows us to climb up to the top-level constraint and
3834 * look for all possible relations referencing the partitioned table.
3835 */
3836 if (OidIsValid(con->conparentid) &&
3837 !list_member_oid(parent_cons, con->conparentid))
3838 parent_cons = lappend_oid(parent_cons, con->conparentid);
3839
3840 /*
3841 * Add referencer to result, unless present in input list. (Don't
3842 * worry about dupes: we'll fix that below).
3843 */
3844 if (!list_member_oid(relationIds, con->conrelid))
3845 result = lappend_oid(result, con->conrelid);
3846 }
3847
3849
3850 /*
3851 * Process each parent constraint we found to add the list of referenced
3852 * relations by them to the oids list. If we do add any new such
3853 * relations, redo the first loop above. Also, if we see that the parent
3854 * constraint in turn has a parent, add that so that we process all
3855 * relations in a single additional pass.
3856 */
3857 foreach(cell, parent_cons)
3858 {
3859 Oid parent = lfirst_oid(cell);
3860
3861 ScanKeyInit(&key,
3864 ObjectIdGetDatum(parent));
3865
3867 true, NULL, 1, &key);
3868
3869 tuple = systable_getnext(fkeyScan);
3870 if (HeapTupleIsValid(tuple))
3871 {
3873
3874 /*
3875 * pg_constraint rows always appear for partitioned hierarchies
3876 * this way: on the each side of the constraint, one row appears
3877 * for each partition that points to the top-most table on the
3878 * other side.
3879 *
3880 * Because of this arrangement, we can correctly catch all
3881 * relevant relations by adding to 'parent_cons' all rows with
3882 * valid conparentid, and to the 'oids' list all rows with a zero
3883 * conparentid. If any oids are added to 'oids', redo the first
3884 * loop above by setting 'restart'.
3885 */
3886 if (OidIsValid(con->conparentid))
3888 con->conparentid);
3889 else if (!list_member_oid(oids, con->confrelid))
3890 {
3891 oids = lappend_oid(oids, con->confrelid);
3892 restart = true;
3893 }
3894 }
3895
3897 }
3898
3900 if (restart)
3901 goto restart;
3902
3904 list_free(oids);
3905
3906 /* Now sort and de-duplicate the result list */
3909
3910 return result;
3911}
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 3652 of file heap.c.

3653{
3655
3656 /*
3657 * Truncate the relation. Partitioned tables have no storage, so there is
3658 * nothing to do for them here.
3659 */
3660 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3661 return;
3662
3663 /* Truncate the underlying relation */
3665
3666 /* If the relation has indexes, truncate the indexes too */
3668
3669 /* If there is a toast table, truncate that too */
3670 toastrelid = rel->rd_rel->reltoastrelid;
3672 {
3674
3677 /* keep the lock... */
3679 }
3680}
static void RelationTruncateIndexes(Relation heapRelation)
Definition heap.c:3562
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 732 of file heap.c.

737{
738 TupleTableSlot **slot;
739 TupleDesc td;
740 int nslots;
741 int natts = 0;
742 int slotCount = 0;
743 bool close_index = false;
744
746
747 /* Initialize the number of slots to use */
748 nslots = Min(tupdesc->natts,
750 slot = palloc_array(TupleTableSlot *, nslots);
751 for (int i = 0; i < nslots; i++)
753
754 while (natts < tupdesc->natts)
755 {
756 Form_pg_attribute attrs = TupleDescAttr(tupdesc, natts);
758
760
761 memset(slot[slotCount]->tts_isnull, false,
762 slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool));
763
764 if (new_rel_oid != InvalidOid)
766 else
768
788 if (attrs_extra)
789 {
790 slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.value;
791 slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.isnull;
792
793 slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.value;
794 slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.isnull;
795 }
796 else
797 {
800 }
801
802 /*
803 * The remaining fields are not set for new columns.
804 */
808
810 slotCount++;
811
812 /*
813 * If slots are full or the end of processing has been reached, insert
814 * a batch of tuples.
815 */
816 if (slotCount == nslots || natts == tupdesc->natts - 1)
817 {
818 /* fetch index info only when we know we need it */
819 if (!indstate)
820 {
822 close_index = true;
823 }
824
825 /* insert the new tuples and update the indexes */
827 indstate);
828 slotCount = 0;
829 }
830
831 natts++;
832 }
833
834 if (close_index)
836 for (int i = 0; i < nslots; i++)
838 pfree(slot);
839}
#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:91
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 928 of file heap.c.

933{
934 Form_pg_class rd_rel = new_rel_desc->rd_rel;
936 bool nulls[Natts_pg_class];
938
939 /* This is a tad tedious, but way cleaner than what we used to do... */
940 memset(values, 0, sizeof(values));
941 memset(nulls, false, sizeof(nulls));
942
944 values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
945 values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
946 values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
947 values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
948 values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
949 values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
950 values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
951 values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
952 values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
953 values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
954 values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
955 values[Anum_pg_class_relallfrozen - 1] = Int32GetDatum(rd_rel->relallfrozen);
956 values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
957 values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
958 values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
959 values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
960 values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
961 values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
962 values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
963 values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
964 values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
965 values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
966 values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
967 values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
968 values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
969 values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
970 values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
971 values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
972 values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
973 values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
974 if (relacl != (Datum) 0)
976 else
977 nulls[Anum_pg_class_relacl - 1] = true;
978 if (reloptions != (Datum) 0)
979 values[Anum_pg_class_reloptions - 1] = reloptions;
980 else
981 nulls[Anum_pg_class_reloptions - 1] = true;
982
983 /* relpartbound is set by updating this tuple, if necessary */
984 nulls[Anum_pg_class_relpartbound - 1] = true;
985
987
988 /* finally insert the new tuple, update the indexes, and clean up */
990
992}
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 2732 of file heap.c.

2737{
2738 bool found;
2741 ScanKeyData skey[3];
2742 HeapTuple tup;
2743
2744 /* Search for a pg_constraint entry with same name and relation */
2746
2747 found = false;
2748
2749 ScanKeyInit(&skey[0],
2753 ScanKeyInit(&skey[1],
2757 ScanKeyInit(&skey[2],
2760 CStringGetDatum(ccname));
2761
2763 NULL, 3, skey);
2764
2765 /* There can be at most one matching row */
2767 {
2769
2770 /* Found it. Conflicts if not identical check constraint */
2771 if (con->contype == CONSTRAINT_CHECK)
2772 {
2773 Datum val;
2774 bool isnull;
2775
2778 conDesc->rd_att, &isnull);
2779 if (isnull)
2780 elog(ERROR, "null conbin for rel %s",
2783 found = true;
2784 }
2785
2786 /*
2787 * If the existing constraint is purely inherited (no local
2788 * definition) then interpret addition of a local constraint as a
2789 * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
2790 * tables to be given in either order with same end state. However if
2791 * the relation is a partition, all inherited constraints are always
2792 * non-local, including those that were merged.
2793 */
2794 if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2795 allow_merge = true;
2796
2797 if (!found || !allow_merge)
2798 ereport(ERROR,
2800 errmsg("constraint \"%s\" for relation \"%s\" already exists",
2801 ccname, RelationGetRelationName(rel))));
2802
2803 /* If the child constraint is "no inherit" then cannot merge */
2804 if (con->connoinherit)
2805 ereport(ERROR,
2807 errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2808 ccname, RelationGetRelationName(rel))));
2809
2810 /*
2811 * Must not change an existing inherited constraint to "no inherit"
2812 * status. That's because inherited constraints should be able to
2813 * propagate to lower-level children.
2814 */
2815 if (con->coninhcount > 0 && is_no_inherit)
2816 ereport(ERROR,
2818 errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2819 ccname, RelationGetRelationName(rel))));
2820
2821 /*
2822 * If the child constraint is "not valid" then cannot merge with a
2823 * valid parent constraint.
2824 */
2825 if (is_initially_valid && con->conenforced && !con->convalidated)
2826 ereport(ERROR,
2828 errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2829 ccname, RelationGetRelationName(rel))));
2830
2831 /*
2832 * A non-enforced child constraint cannot be merged with an enforced
2833 * parent constraint. However, the reverse is allowed, where the child
2834 * constraint is enforced.
2835 */
2836 if ((!is_local && is_enforced && !con->conenforced) ||
2837 (is_local && !is_enforced && con->conenforced))
2838 ereport(ERROR,
2840 errmsg("constraint \"%s\" conflicts with NOT ENFORCED constraint on relation \"%s\"",
2841 ccname, RelationGetRelationName(rel))));
2842
2843 /* OK to update the tuple */
2845 (errmsg("merging constraint \"%s\" with inherited definition",
2846 ccname)));
2847
2850
2851 /*
2852 * In case of partitions, an inherited constraint must be inherited
2853 * only once since it cannot have multiple parents and it is never
2854 * considered local.
2855 */
2856 if (rel->rd_rel->relispartition)
2857 {
2858 con->coninhcount = 1;
2859 con->conislocal = false;
2860 }
2861 else
2862 {
2863 if (is_local)
2864 con->conislocal = true;
2865 else if (pg_add_s16_overflow(con->coninhcount, 1,
2866 &con->coninhcount))
2867 ereport(ERROR,
2869 errmsg("too many inheritance parents"));
2870 }
2871
2872 if (is_no_inherit)
2873 {
2874 Assert(is_local);
2875 con->connoinherit = true;
2876 }
2877
2878 /*
2879 * If the child constraint is required to be enforced while the parent
2880 * constraint is not, this should be allowed by marking the child
2881 * constraint as enforced. In the reverse case, an error would have
2882 * already been thrown before reaching this point.
2883 */
2884 if (is_enforced && !con->conenforced)
2885 {
2886 Assert(is_local);
2887 con->conenforced = true;
2888 con->convalidated = true;
2889 }
2890
2891 CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2892 }
2893
2896
2897 return found;
2898}
#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 1984 of file heap.c.

1985{
1987 Oid relid = RelationGetRelid(rel);
1988 int natts = RelationGetNumberOfAttributes(rel);
1989 int attnum;
1994 HeapTuple tuple,
1995 newtuple;
1996
1997 memset(repl_val, 0, sizeof(repl_val));
1998 memset(repl_null, false, sizeof(repl_null));
1999 memset(repl_repl, false, sizeof(repl_repl));
2000
2003
2006
2007
2008 /* Get a lock on pg_attribute */
2010
2011 /* process each non-system attribute, including any dropped columns */
2012 for (attnum = 1; attnum <= natts; attnum++)
2013 {
2014 tuple = SearchSysCache2(ATTNUM,
2015 ObjectIdGetDatum(relid),
2017 if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2018 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2019 attnum, relid);
2020
2022
2023 /* ignore any where atthasmissing is not true */
2024 if (attrtuple->atthasmissing)
2025 {
2026 newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2028
2029 CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2030
2031 heap_freetuple(newtuple);
2032 }
2033
2034 ReleaseSysCache(tuple);
2035 }
2036
2037 /*
2038 * Our update of the pg_attribute rows will force a relcache rebuild, so
2039 * there's nothing else to do here.
2040 */
2042}
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 3562 of file heap.c.

3563{
3565
3566 /* Ask the relcache to produce a list of the indexes of the rel */
3567 foreach(indlist, RelationGetIndexList(heapRelation))
3568 {
3571 IndexInfo *indexInfo;
3572
3573 /* Open the index relation; use exclusive lock, just to be sure */
3575
3576 /*
3577 * Fetch info needed for index_build. Since we know there are no
3578 * tuples that actually need indexing, we can use a dummy IndexInfo.
3579 * This is slightly cheaper to build, but the real point is to avoid
3580 * possibly running user-defined code in index expressions or
3581 * predicates. We might be getting invoked during ON COMMIT
3582 * processing, and we don't want to run any such code then.
3583 */
3584 indexInfo = BuildDummyIndexInfo(currentIndex);
3585
3586 /*
3587 * Now truncate the actual file (and discard buffers).
3588 */
3590
3591 /* Initialize the index and rebuild */
3592 /* Note: we do not need to re-establish pkey setting */
3593 index_build(heapRelation, currentIndex, indexInfo, true, false,
3594 true);
3595
3596 /* We're done with this index */
3598 }
3599}
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:4837
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 1703 of file heap.c.

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

4044{
4045 Relation rel;
4046 HeapTuple tuple;
4047
4049
4051 if (!HeapTupleIsValid(tuple))
4052 elog(ERROR, "cache lookup failed for partition key of relation %u",
4053 relid);
4054
4055 CatalogTupleDelete(rel, &tuple->t_self);
4056
4057 ReleaseSysCache(tuple);
4059}

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 3515 of file heap.c.

3516{
3518 SysScanDesc scan;
3519 ScanKeyData key[2];
3520 int nkeys;
3521 HeapTuple tuple;
3522
3524
3525 ScanKeyInit(&key[0],
3528 ObjectIdGetDatum(relid));
3529
3530 if (attnum == 0)
3531 nkeys = 1;
3532 else
3533 {
3534 ScanKeyInit(&key[1],
3538 nkeys = 2;
3539 }
3540
3542 NULL, nkeys, key);
3543
3544 /* we must loop even when attnum != 0, in case of inherited stats */
3545 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3547
3548 systable_endscan(scan);
3549
3551}

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 2106 of file heap.c.

2107{
2109 bool nullsAtt[Natts_pg_attribute] = {0};
2110 bool replacesAtt[Natts_pg_attribute] = {0};
2114 tablerel;
2116 newtup;
2117
2118 /* lock the table the attribute belongs to */
2120
2121 /* Don't do anything unless it's a plain table */
2122 if (tablerel->rd_rel->relkind != RELKIND_RELATION)
2123 {
2125 return;
2126 }
2127
2128 /* Lock the attribute row and get the data */
2132 elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2133 attname, relid);
2135
2136 /* get an array value from the value string */
2139 ObjectIdGetDatum(attStruct->atttypid),
2140 Int32GetDatum(attStruct->atttypmod));
2141
2142 /* update the tuple - set atthasmissing and attmissingval */
2147
2151
2152 /* clean up */
2156}
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition fmgr.h:730
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 3169 of file heap.c.

3170{
3174
3179 elog(ERROR, "cache lookup failed for relation %u",
3180 RelationGetRelid(rel));
3182
3183 if (relStruct->relchecks != numchecks)
3184 {
3185 relStruct->relchecks = numchecks;
3186
3188 }
3189 else
3190 {
3191 /* Skip the disk update, but force relcache inval anyway */
3193 }
3194
3197}
void CacheInvalidateRelcache(Relation relation)
Definition inval.c:1632
#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 2050 of file heap.c.

2051{
2053 bool nullsAtt[Natts_pg_attribute] = {0};
2054 bool replacesAtt[Natts_pg_attribute] = {0};
2058 newtup;
2059
2060 /* This is only supported for plain tables */
2061 Assert(rel->rd_rel->relkind == RELKIND_RELATION);
2062
2063 /* Fetch the pg_attribute row */
2065
2069 if (!HeapTupleIsValid(atttup)) /* shouldn't happen */
2070 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2071 attnum, RelationGetRelid(rel));
2073
2074 /* Make a one-element array containing the value */
2076 1,
2077 attStruct->atttypid,
2078 attStruct->attlen,
2079 attStruct->attbyval,
2080 attStruct->attalign));
2081
2082 /* Update the pg_attribute row */
2085
2088
2092
2093 /* clean up */
2096}
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 2330 of file heap.c.

2331{
2332 int numchecks = 0;
2333 ListCell *lc;
2334
2335 if (cooked_constraints == NIL)
2336 return; /* nothing to do */
2337
2338 /*
2339 * Deparsing of constraint expressions will fail unless the just-created
2340 * pg_attribute tuples for this relation are made visible. So, bump the
2341 * command counter. CAUTION: this will cause a relcache entry rebuild.
2342 */
2344
2345 foreach(lc, cooked_constraints)
2346 {
2348
2349 switch (con->contype)
2350 {
2351 case CONSTR_DEFAULT:
2352 con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
2353 is_internal);
2354 break;
2355 case CONSTR_CHECK:
2356 con->conoid =
2357 StoreRelCheck(rel, con->name, con->expr,
2358 con->is_enforced, !con->skip_validation,
2359 con->is_local, con->inhcount,
2360 con->is_no_inherit, is_internal);
2361 numchecks++;
2362 break;
2363
2364 default:
2365 elog(ERROR, "unrecognized constraint type: %d",
2366 (int) con->contype);
2367 }
2368 }
2369
2370 if (numchecks > 0)
2372}
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 4074 of file heap.c.

4075{
4077 HeapTuple tuple,
4078 newtuple;
4083
4084 /* Update pg_class tuple */
4088 if (!HeapTupleIsValid(tuple))
4089 elog(ERROR, "cache lookup failed for relation %u",
4090 RelationGetRelid(rel));
4091
4092#ifdef USE_ASSERT_CHECKING
4093 {
4095 bool isnull;
4096
4098 Assert(!classForm->relispartition);
4100 &isnull);
4101 Assert(isnull);
4102 }
4103#endif
4104
4105 /* Fill in relpartbound value */
4106 memset(new_val, 0, sizeof(new_val));
4107 memset(new_null, false, sizeof(new_null));
4108 memset(new_repl, false, sizeof(new_repl));
4112 newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
4114 /* Also set the flag */
4115 ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
4116
4117 /*
4118 * We already checked for no inheritance children, but reset
4119 * relhassubclass in case it was left over.
4120 */
4121 if (rel->rd_rel->relkind == RELKIND_RELATION && rel->rd_rel->relhassubclass)
4122 ((Form_pg_class) GETSTRUCT(newtuple))->relhassubclass = false;
4123
4124 CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
4125 heap_freetuple(newtuple);
4127
4128 /*
4129 * If we're storing bounds for the default partition, update
4130 * pg_partitioned_table too.
4131 */
4132 if (bound->is_default)
4134 RelationGetRelid(rel));
4135
4136 /* Make these updates visible */
4138
4139 /*
4140 * The partition constraint for the default partition depends on the
4141 * partition bounds of every other partition, so we must invalidate the
4142 * relcache entry for that partition every time a partition is added or
4143 * removed.
4144 */
4149
4151}
#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 3918 of file heap.c.

3925{
3926 int i;
3932 HeapTuple tuple;
3934 bool nulls[Natts_pg_partitioned_table] = {0};
3937 ObjectAddresses *addrs;
3938
3939 Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3940
3941 /* Copy the partition attribute numbers, opclass OIDs into arrays */
3942 partattrs_vec = buildint2vector(partattrs, partnatts);
3944 partcollation_vec = buildoidvector(partcollation, partnatts);
3945
3946 /* Convert the expressions (if any) to a text datum */
3947 if (partexprs)
3948 {
3949 char *exprString;
3950
3951 exprString = nodeToString(partexprs);
3954 }
3955 else
3956 partexprDatum = (Datum) 0;
3957
3959
3960 /* Only this can ever be NULL */
3961 if (!partexprDatum)
3962 nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3963
3972
3974
3977
3978 /* Mark this relation as dependent on a few things as follows */
3979 addrs = new_object_addresses();
3981
3982 /* Operator class and collation per key column */
3983 for (i = 0; i < partnatts; i++)
3984 {
3987
3988 /* The default collation is pinned, so don't bother recording it */
3989 if (OidIsValid(partcollation[i]) &&
3990 partcollation[i] != DEFAULT_COLLATION_OID)
3991 {
3994 }
3995 }
3996
3998 free_object_addresses(addrs);
3999
4000 /*
4001 * The partitioning columns are made internally dependent on the table,
4002 * because we cannot drop any of them without dropping the whole table.
4003 * (ATExecDropColumn independently enforces that, but it's not bulletproof
4004 * so we need the dependencies too.)
4005 */
4006 for (i = 0; i < partnatts; i++)
4007 {
4008 if (partattrs[i] == 0)
4009 continue; /* ignore expressions here */
4010
4012 RelationGetRelid(rel), partattrs[i]);
4014 }
4015
4016 /*
4017 * Also consider anything mentioned in partition expressions. External
4018 * references (e.g. functions) get NORMAL dependencies. Table columns
4019 * mentioned in the expressions are handled the same as plain partitioning
4020 * columns, i.e. they become internally dependent on the whole table.
4021 */
4022 if (partexprs)
4024 (Node *) partexprs,
4025 RelationGetRelid(rel),
4028 true /* reverse the self-deps */ );
4029
4030 /*
4031 * We must invalidate the relcache so that the next
4032 * CommandCounterIncrement() will cause the same to be rebuilt using the
4033 * information in just created catalog entry.
4034 */
4036}
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 2167 of file heap.c.

2170{
2171 char *ccbin;
2172 List *varList;
2173 int keycount;
2174 int16 *attNos;
2175 Oid constrOid;
2176
2177 /*
2178 * Flatten expression to string form for storage.
2179 */
2180 ccbin = nodeToString(expr);
2181
2182 /*
2183 * Find columns of rel that are used in expr
2184 *
2185 * NB: pull_var_clause is okay here only because we don't allow subselects
2186 * in check constraints; it would fail to examine the contents of
2187 * subselects.
2188 */
2189 varList = pull_var_clause(expr, 0);
2191
2192 if (keycount > 0)
2193 {
2194 ListCell *vl;
2195 int i = 0;
2196
2197 attNos = (int16 *) palloc(keycount * sizeof(int16));
2198 foreach(vl, varList)
2199 {
2200 Var *var = (Var *) lfirst(vl);
2201 int j;
2202
2203 for (j = 0; j < i; j++)
2204 if (attNos[j] == var->varattno)
2205 break;
2206 if (j == i)
2207 attNos[i++] = var->varattno;
2208 }
2209 keycount = i;
2210 }
2211 else
2212 attNos = NULL;
2213
2214 /*
2215 * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2216 * constraint makes no sense.
2217 */
2218 if (is_no_inherit &&
2219 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2220 ereport(ERROR,
2222 errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2224
2225 /*
2226 * Create the Check Constraint
2227 */
2228 constrOid =
2229 CreateConstraintEntry(ccname, /* Constraint Name */
2230 RelationGetNamespace(rel), /* namespace */
2231 CONSTRAINT_CHECK, /* Constraint Type */
2232 false, /* Is Deferrable */
2233 false, /* Is Deferred */
2234 is_enforced, /* Is Enforced */
2236 InvalidOid, /* no parent constraint */
2237 RelationGetRelid(rel), /* relation */
2238 attNos, /* attrs in the constraint */
2239 keycount, /* # key attrs in the constraint */
2240 keycount, /* # total attrs in the constraint */
2241 InvalidOid, /* not a domain constraint */
2242 InvalidOid, /* no associated index */
2243 InvalidOid, /* Foreign key fields */
2244 NULL,
2245 NULL,
2246 NULL,
2247 NULL,
2248 0,
2249 ' ',
2250 ' ',
2251 NULL,
2252 0,
2253 ' ',
2254 NULL, /* not an exclusion constraint */
2255 expr, /* Tree form of check constraint */
2256 ccbin, /* Binary form of check constraint */
2257 is_local, /* conislocal */
2258 inhcount, /* coninhcount */
2259 is_no_inherit, /* connoinherit */
2260 false, /* conperiod */
2261 is_internal); /* internally constructed? */
2262
2263 pfree(ccbin);
2264
2265 return constrOid;
2266}
void * palloc(Size size)
Definition mcxt.c:1390
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 2274 of file heap.c.

2277{
2278 Oid constrOid;
2279
2281
2282 constrOid =
2286 false,
2287 false,
2288 true, /* Is Enforced */
2290 InvalidOid,
2291 RelationGetRelid(rel),
2292 &attnum,
2293 1,
2294 1,
2295 InvalidOid, /* not a domain constraint */
2296 InvalidOid, /* no associated index */
2297 InvalidOid, /* Foreign key fields */
2298 NULL,
2299 NULL,
2300 NULL,
2301 NULL,
2302 0,
2303 ' ',
2304 ' ',
2305 NULL,
2306 0,
2307 ' ',
2308 NULL, /* not an exclusion constraint */
2309 NULL,
2310 NULL,
2311 is_local,
2312 inhcount,
2313 is_no_inherit,
2314 false,
2315 false);
2316 return constrOid;
2317}

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().