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