PostgreSQL Source Code git master
tablecmds.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * tablecmds.c
4 * Commands for creating and altering table structures and settings
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/commands/tablecmds.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include "access/attmap.h"
18#include "access/genam.h"
19#include "access/gist.h"
20#include "access/heapam.h"
21#include "access/heapam_xlog.h"
22#include "access/multixact.h"
23#include "access/reloptions.h"
24#include "access/relscan.h"
25#include "access/sysattr.h"
26#include "access/tableam.h"
28#include "access/xact.h"
29#include "access/xlog.h"
30#include "access/xloginsert.h"
31#include "catalog/catalog.h"
32#include "catalog/heap.h"
33#include "catalog/index.h"
34#include "catalog/namespace.h"
36#include "catalog/partition.h"
37#include "catalog/pg_am.h"
38#include "catalog/pg_attrdef.h"
41#include "catalog/pg_depend.h"
43#include "catalog/pg_inherits.h"
46#include "catalog/pg_opclass.h"
47#include "catalog/pg_policy.h"
48#include "catalog/pg_proc.h"
50#include "catalog/pg_rewrite.h"
53#include "catalog/pg_trigger.h"
54#include "catalog/pg_type.h"
55#include "catalog/storage.h"
57#include "catalog/toasting.h"
58#include "commands/cluster.h"
59#include "commands/comment.h"
60#include "commands/defrem.h"
62#include "commands/sequence.h"
63#include "commands/tablecmds.h"
64#include "commands/tablespace.h"
65#include "commands/trigger.h"
66#include "commands/typecmds.h"
67#include "commands/user.h"
68#include "commands/vacuum.h"
69#include "common/int.h"
70#include "executor/executor.h"
71#include "foreign/fdwapi.h"
72#include "foreign/foreign.h"
73#include "miscadmin.h"
74#include "nodes/makefuncs.h"
75#include "nodes/nodeFuncs.h"
76#include "nodes/parsenodes.h"
77#include "optimizer/optimizer.h"
78#include "parser/parse_coerce.h"
80#include "parser/parse_expr.h"
82#include "parser/parse_type.h"
84#include "parser/parser.h"
87#include "pgstat.h"
91#include "storage/bufmgr.h"
92#include "storage/lmgr.h"
93#include "storage/lock.h"
94#include "storage/predicate.h"
95#include "storage/smgr.h"
96#include "tcop/utility.h"
97#include "utils/acl.h"
98#include "utils/builtins.h"
99#include "utils/fmgroids.h"
100#include "utils/inval.h"
101#include "utils/lsyscache.h"
102#include "utils/memutils.h"
103#include "utils/partcache.h"
104#include "utils/relcache.h"
105#include "utils/ruleutils.h"
106#include "utils/snapmgr.h"
107#include "utils/syscache.h"
108#include "utils/timestamp.h"
109#include "utils/typcache.h"
110#include "utils/usercontext.h"
111
112/*
113 * ON COMMIT action list
114 */
115typedef struct OnCommitItem
116{
117 Oid relid; /* relid of relation */
118 OnCommitAction oncommit; /* what to do at end of xact */
119
120 /*
121 * If this entry was created during the current transaction,
122 * creating_subid is the ID of the creating subxact; if created in a prior
123 * transaction, creating_subid is zero. If deleted during the current
124 * transaction, deleting_subid is the ID of the deleting subxact; if no
125 * deletion request is pending, deleting_subid is zero.
126 */
130
132
133
134/*
135 * State information for ALTER TABLE
136 *
137 * The pending-work queue for an ALTER TABLE is a List of AlteredTableInfo
138 * structs, one for each table modified by the operation (the named table
139 * plus any child tables that are affected). We save lists of subcommands
140 * to apply to this table (possibly modified by parse transformation steps);
141 * these lists will be executed in Phase 2. If a Phase 3 step is needed,
142 * necessary information is stored in the constraints and newvals lists.
143 *
144 * Phase 2 is divided into multiple passes; subcommands are executed in
145 * a pass determined by subcommand type.
146 */
147
148typedef enum AlterTablePass
149{
150 AT_PASS_UNSET = -1, /* UNSET will cause ERROR */
151 AT_PASS_DROP, /* DROP (all flavors) */
152 AT_PASS_ALTER_TYPE, /* ALTER COLUMN TYPE */
153 AT_PASS_ADD_COL, /* ADD COLUMN */
154 AT_PASS_SET_EXPRESSION, /* ALTER SET EXPRESSION */
155 AT_PASS_OLD_INDEX, /* re-add existing indexes */
156 AT_PASS_OLD_CONSTR, /* re-add existing constraints */
157 /* We could support a RENAME COLUMN pass here, but not currently used */
158 AT_PASS_ADD_CONSTR, /* ADD constraints (initial examination) */
159 AT_PASS_COL_ATTRS, /* set column attributes, eg NOT NULL */
160 AT_PASS_ADD_INDEXCONSTR, /* ADD index-based constraints */
161 AT_PASS_ADD_INDEX, /* ADD indexes */
162 AT_PASS_ADD_OTHERCONSTR, /* ADD other constraints, defaults */
163 AT_PASS_MISC, /* other stuff */
165
166#define AT_NUM_PASSES (AT_PASS_MISC + 1)
167
168typedef struct AlteredTableInfo
169{
170 /* Information saved before any work commences: */
171 Oid relid; /* Relation to work on */
172 char relkind; /* Its relkind */
173 TupleDesc oldDesc; /* Pre-modification tuple descriptor */
174
175 /*
176 * Transiently set during Phase 2, normally set to NULL.
177 *
178 * ATRewriteCatalogs sets this when it starts, and closes when ATExecCmd
179 * returns control. This can be exploited by ATExecCmd subroutines to
180 * close/reopen across transaction boundaries.
181 */
183
184 /* Information saved by Phase 1 for Phase 2: */
185 List *subcmds[AT_NUM_PASSES]; /* Lists of AlterTableCmd */
186 /* Information saved by Phases 1/2 for Phase 3: */
187 List *constraints; /* List of NewConstraint */
188 List *newvals; /* List of NewColumnValue */
189 List *afterStmts; /* List of utility command parsetrees */
190 bool verify_new_notnull; /* T if we should recheck NOT NULL */
191 int rewrite; /* Reason for forced rewrite, if any */
192 bool chgAccessMethod; /* T if SET ACCESS METHOD is used */
193 Oid newAccessMethod; /* new access method; 0 means no change,
194 * if above is true */
195 Oid newTableSpace; /* new tablespace; 0 means no change */
196 bool chgPersistence; /* T if SET LOGGED/UNLOGGED is used */
197 char newrelpersistence; /* if above is true */
198 Expr *partition_constraint; /* for attach partition validation */
199 /* true, if validating default due to some other attach/detach */
201 /* Objects to rebuild after completing ALTER TYPE operations */
202 List *changedConstraintOids; /* OIDs of constraints to rebuild */
203 List *changedConstraintDefs; /* string definitions of same */
204 List *changedIndexOids; /* OIDs of indexes to rebuild */
205 List *changedIndexDefs; /* string definitions of same */
206 char *replicaIdentityIndex; /* index to reset as REPLICA IDENTITY */
207 char *clusterOnIndex; /* index to use for CLUSTER */
208 List *changedStatisticsOids; /* OIDs of statistics to rebuild */
209 List *changedStatisticsDefs; /* string definitions of same */
211
212/* Struct describing one new constraint to check in Phase 3 scan */
213/* Note: new not-null constraints are handled elsewhere */
214typedef struct NewConstraint
215{
216 char *name; /* Constraint name, or NULL if none */
217 ConstrType contype; /* CHECK or FOREIGN */
218 Oid refrelid; /* PK rel, if FOREIGN */
219 Oid refindid; /* OID of PK's index, if FOREIGN */
220 bool conwithperiod; /* Whether the new FOREIGN KEY uses PERIOD */
221 Oid conid; /* OID of pg_constraint entry, if FOREIGN */
222 Node *qual; /* Check expr or CONSTR_FOREIGN Constraint */
223 ExprState *qualstate; /* Execution state for CHECK expr */
225
226/*
227 * Struct describing one new column value that needs to be computed during
228 * Phase 3 copy (this could be either a new column with a non-null default, or
229 * a column that we're changing the type of). Columns without such an entry
230 * are just copied from the old table during ATRewriteTable. Note that the
231 * expr is an expression over *old* table values, except when is_generated
232 * is true; then it is an expression over columns of the *new* tuple.
233 */
234typedef struct NewColumnValue
235{
236 AttrNumber attnum; /* which column */
237 Expr *expr; /* expression to compute */
238 ExprState *exprstate; /* execution state */
239 bool is_generated; /* is it a GENERATED expression? */
241
242/*
243 * Error-reporting support for RemoveRelations
244 */
246{
247 char kind;
249 const char *nonexistent_msg;
250 const char *skipping_msg;
251 const char *nota_msg;
252 const char *drophint_msg;
253};
254
255static const struct dropmsgstrings dropmsgstringarray[] = {
256 {RELKIND_RELATION,
258 gettext_noop("table \"%s\" does not exist"),
259 gettext_noop("table \"%s\" does not exist, skipping"),
260 gettext_noop("\"%s\" is not a table"),
261 gettext_noop("Use DROP TABLE to remove a table.")},
262 {RELKIND_SEQUENCE,
264 gettext_noop("sequence \"%s\" does not exist"),
265 gettext_noop("sequence \"%s\" does not exist, skipping"),
266 gettext_noop("\"%s\" is not a sequence"),
267 gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
268 {RELKIND_VIEW,
270 gettext_noop("view \"%s\" does not exist"),
271 gettext_noop("view \"%s\" does not exist, skipping"),
272 gettext_noop("\"%s\" is not a view"),
273 gettext_noop("Use DROP VIEW to remove a view.")},
274 {RELKIND_MATVIEW,
276 gettext_noop("materialized view \"%s\" does not exist"),
277 gettext_noop("materialized view \"%s\" does not exist, skipping"),
278 gettext_noop("\"%s\" is not a materialized view"),
279 gettext_noop("Use DROP MATERIALIZED VIEW to remove a materialized view.")},
280 {RELKIND_INDEX,
281 ERRCODE_UNDEFINED_OBJECT,
282 gettext_noop("index \"%s\" does not exist"),
283 gettext_noop("index \"%s\" does not exist, skipping"),
284 gettext_noop("\"%s\" is not an index"),
285 gettext_noop("Use DROP INDEX to remove an index.")},
286 {RELKIND_COMPOSITE_TYPE,
287 ERRCODE_UNDEFINED_OBJECT,
288 gettext_noop("type \"%s\" does not exist"),
289 gettext_noop("type \"%s\" does not exist, skipping"),
290 gettext_noop("\"%s\" is not a type"),
291 gettext_noop("Use DROP TYPE to remove a type.")},
292 {RELKIND_FOREIGN_TABLE,
293 ERRCODE_UNDEFINED_OBJECT,
294 gettext_noop("foreign table \"%s\" does not exist"),
295 gettext_noop("foreign table \"%s\" does not exist, skipping"),
296 gettext_noop("\"%s\" is not a foreign table"),
297 gettext_noop("Use DROP FOREIGN TABLE to remove a foreign table.")},
298 {RELKIND_PARTITIONED_TABLE,
300 gettext_noop("table \"%s\" does not exist"),
301 gettext_noop("table \"%s\" does not exist, skipping"),
302 gettext_noop("\"%s\" is not a table"),
303 gettext_noop("Use DROP TABLE to remove a table.")},
304 {RELKIND_PARTITIONED_INDEX,
305 ERRCODE_UNDEFINED_OBJECT,
306 gettext_noop("index \"%s\" does not exist"),
307 gettext_noop("index \"%s\" does not exist, skipping"),
308 gettext_noop("\"%s\" is not an index"),
309 gettext_noop("Use DROP INDEX to remove an index.")},
310 {'\0', 0, NULL, NULL, NULL, NULL}
311};
312
313/* communication between RemoveRelations and RangeVarCallbackForDropRelation */
315{
316 /* These fields are set by RemoveRelations: */
319 /* These fields are state to track which subsidiary locks are held: */
322 /* These fields are passed back by RangeVarCallbackForDropRelation: */
325};
326
327/* Alter table target-type flags for ATSimplePermissions */
328#define ATT_TABLE 0x0001
329#define ATT_VIEW 0x0002
330#define ATT_MATVIEW 0x0004
331#define ATT_INDEX 0x0008
332#define ATT_COMPOSITE_TYPE 0x0010
333#define ATT_FOREIGN_TABLE 0x0020
334#define ATT_PARTITIONED_INDEX 0x0040
335#define ATT_SEQUENCE 0x0080
336#define ATT_PARTITIONED_TABLE 0x0100
337
338/*
339 * ForeignTruncateInfo
340 *
341 * Information related to truncation of foreign tables. This is used for
342 * the elements in a hash table. It uses the server OID as lookup key,
343 * and includes a per-server list of all foreign tables involved in the
344 * truncation.
345 */
347{
351
352/* Partial or complete FK creation in addFkConstraint() */
354{
359
360/*
361 * Partition tables are expected to be dropped when the parent partitioned
362 * table gets dropped. Hence for partitioning we use AUTO dependency.
363 * Otherwise, for regular inheritance use NORMAL dependency.
364 */
365#define child_dependency_type(child_is_partition) \
366 ((child_is_partition) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL)
367
368static void truncate_check_rel(Oid relid, Form_pg_class reltuple);
369static void truncate_check_perms(Oid relid, Form_pg_class reltuple);
370static void truncate_check_activity(Relation rel);
371static void RangeVarCallbackForTruncate(const RangeVar *relation,
372 Oid relId, Oid oldRelId, void *arg);
373static List *MergeAttributes(List *columns, const List *supers, char relpersistence,
374 bool is_partition, List **supconstr,
375 List **supnotnulls);
376static List *MergeCheckConstraint(List *constraints, const char *name, Node *expr, bool is_enforced);
377static void MergeChildAttribute(List *inh_columns, int exist_attno, int newcol_attno, const ColumnDef *newdef);
378static ColumnDef *MergeInheritedAttribute(List *inh_columns, int exist_attno, const ColumnDef *newdef);
379static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispartition);
380static void MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel);
381static void StoreCatalogInheritance(Oid relationId, List *supers,
382 bool child_is_partition);
383static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
384 int32 seqNumber, Relation inhRelation,
385 bool child_is_partition);
386static int findAttrByName(const char *attributeName, const List *columns);
387static void AlterIndexNamespaces(Relation classRel, Relation rel,
388 Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved);
389static void AlterSeqNamespaces(Relation classRel, Relation rel,
390 Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
391 LOCKMODE lockmode);
393 bool recurse, bool recursing, LOCKMODE lockmode);
394static bool ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
395 Relation rel, HeapTuple contuple, List **otherrelids,
396 LOCKMODE lockmode);
397static void AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
398 bool deferrable, bool initdeferred,
399 List **otherrelids);
400static void ATExecAlterChildConstr(Constraint *cmdcon, Relation conrel, Relation tgrel,
401 Relation rel, HeapTuple contuple, List **otherrelids,
402 LOCKMODE lockmode);
404 Relation rel, char *constrName,
405 bool recurse, bool recursing, LOCKMODE lockmode);
406static void QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation rel,
407 HeapTuple contuple, LOCKMODE lockmode);
408static void QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel,
409 char *constrName, HeapTuple contuple,
410 bool recurse, bool recursing, LOCKMODE lockmode);
411static int transformColumnNameList(Oid relId, List *colList,
412 int16 *attnums, Oid *atttypids, Oid *attcollids);
413static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
414 List **attnamelist,
415 int16 *attnums, Oid *atttypids, Oid *attcollids,
416 Oid *opclasses, bool *pk_has_without_overlaps);
418 int numattrs, int16 *attnums,
419 bool with_period, Oid *opclasses,
420 bool *pk_has_without_overlaps);
421static void checkFkeyPermissions(Relation rel, int16 *attnums, int natts);
422static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
423 Oid *funcid);
424static void validateForeignKeyConstraint(char *conname,
425 Relation rel, Relation pkrel,
426 Oid pkindOid, Oid constraintOid, bool hasperiod);
427static void CheckAlterTableIsSafe(Relation rel);
428static void ATController(AlterTableStmt *parsetree,
429 Relation rel, List *cmds, bool recurse, LOCKMODE lockmode,
430 AlterTableUtilityContext *context);
431static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
432 bool recurse, bool recursing, LOCKMODE lockmode,
433 AlterTableUtilityContext *context);
434static void ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
435 AlterTableUtilityContext *context);
436static void ATExecCmd(List **wqueue, AlteredTableInfo *tab,
437 AlterTableCmd *cmd, LOCKMODE lockmode, AlterTablePass cur_pass,
438 AlterTableUtilityContext *context);
440 Relation rel, AlterTableCmd *cmd,
441 bool recurse, LOCKMODE lockmode,
442 AlterTablePass cur_pass,
443 AlterTableUtilityContext *context);
444static void ATRewriteTables(AlterTableStmt *parsetree,
445 List **wqueue, LOCKMODE lockmode,
446 AlterTableUtilityContext *context);
447static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap);
448static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
449static void ATSimplePermissions(AlterTableType cmdtype, Relation rel, int allowed_targets);
450static void ATSimpleRecursion(List **wqueue, Relation rel,
451 AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode,
452 AlterTableUtilityContext *context);
453static void ATCheckPartitionsNotInUse(Relation rel, LOCKMODE lockmode);
454static void ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
455 LOCKMODE lockmode,
456 AlterTableUtilityContext *context);
457static List *find_typed_table_dependencies(Oid typeOid, const char *typeName,
458 DropBehavior behavior);
459static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
460 bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode,
461 AlterTableUtilityContext *context);
463 Relation rel, AlterTableCmd **cmd,
464 bool recurse, bool recursing,
465 LOCKMODE lockmode, AlterTablePass cur_pass,
466 AlterTableUtilityContext *context);
467static bool check_for_column_name_collision(Relation rel, const char *colname,
468 bool if_not_exists);
469static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
471static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, bool recurse,
472 LOCKMODE lockmode);
473static void set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum,
474 LOCKMODE lockmode);
475static ObjectAddress ATExecSetNotNull(List **wqueue, Relation rel,
476 char *constrname, char *colName,
477 bool recurse, bool recursing,
478 LOCKMODE lockmode);
481 List *testConstraint, List *provenConstraint);
482static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName,
483 Node *newDefault, LOCKMODE lockmode);
485 Node *newDefault);
486static ObjectAddress ATExecAddIdentity(Relation rel, const char *colName,
487 Node *def, LOCKMODE lockmode, bool recurse, bool recursing);
488static ObjectAddress ATExecSetIdentity(Relation rel, const char *colName,
489 Node *def, LOCKMODE lockmode, bool recurse, bool recursing);
490static ObjectAddress ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE lockmode,
491 bool recurse, bool recursing);
492static ObjectAddress ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName,
493 Node *newExpr, LOCKMODE lockmode);
494static void ATPrepDropExpression(Relation rel, AlterTableCmd *cmd, bool recurse, bool recursing, LOCKMODE lockmode);
495static ObjectAddress ATExecDropExpression(Relation rel, const char *colName, bool missing_ok, LOCKMODE lockmode);
496static ObjectAddress ATExecSetStatistics(Relation rel, const char *colName, int16 colNum,
497 Node *newValue, LOCKMODE lockmode);
498static ObjectAddress ATExecSetOptions(Relation rel, const char *colName,
499 Node *options, bool isReset, LOCKMODE lockmode);
500static ObjectAddress ATExecSetStorage(Relation rel, const char *colName,
501 Node *newValue, LOCKMODE lockmode);
502static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
503 AlterTableCmd *cmd, LOCKMODE lockmode,
504 AlterTableUtilityContext *context);
505static ObjectAddress ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
506 DropBehavior behavior,
507 bool recurse, bool recursing,
508 bool missing_ok, LOCKMODE lockmode,
509 ObjectAddresses *addrs);
510static void ATPrepAddPrimaryKey(List **wqueue, Relation rel, AlterTableCmd *cmd,
511 bool recurse, LOCKMODE lockmode,
512 AlterTableUtilityContext *context);
514 IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode);
516 CreateStatsStmt *stmt, bool is_rebuild, LOCKMODE lockmode);
518 AlteredTableInfo *tab, Relation rel,
519 Constraint *newConstraint, bool recurse, bool is_readd,
520 LOCKMODE lockmode);
521static char *ChooseForeignKeyConstraintNameAddition(List *colnames);
523 IndexStmt *stmt, LOCKMODE lockmode);
525 AlteredTableInfo *tab, Relation rel,
526 Constraint *constr,
527 bool recurse, bool recursing, bool is_readd,
528 LOCKMODE lockmode);
530 Relation rel, Constraint *fkconstraint,
531 bool recurse, bool recursing,
532 LOCKMODE lockmode);
533static void validateFkOnDeleteSetColumns(int numfks, const int16 *fkattnums,
534 int numfksetcols, const int16 *fksetcolsattnums,
535 List *fksetcols);
537 char *constraintname,
538 Constraint *fkconstraint, Relation rel,
539 Relation pkrel, Oid indexOid,
540 Oid parentConstr,
541 int numfks, int16 *pkattnum, int16 *fkattnum,
542 Oid *pfeqoperators, Oid *ppeqoperators,
543 Oid *ffeqoperators, int numfkdelsetcols,
544 int16 *fkdelsetcols, bool is_internal,
545 bool with_period);
546static void addFkRecurseReferenced(Constraint *fkconstraint,
547 Relation rel, Relation pkrel, Oid indexOid, Oid parentConstr,
548 int numfks, int16 *pkattnum, int16 *fkattnum,
549 Oid *pfeqoperators, Oid *ppeqoperators, Oid *ffeqoperators,
550 int numfkdelsetcols, int16 *fkdelsetcols,
551 bool old_check_ok,
552 Oid parentDelTrigger, Oid parentUpdTrigger,
553 bool with_period);
554static void addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint,
555 Relation rel, Relation pkrel, Oid indexOid, Oid parentConstr,
556 int numfks, int16 *pkattnum, int16 *fkattnum,
557 Oid *pfeqoperators, Oid *ppeqoperators, Oid *ffeqoperators,
558 int numfkdelsetcols, int16 *fkdelsetcols,
559 bool old_check_ok, LOCKMODE lockmode,
560 Oid parentInsTrigger, Oid parentUpdTrigger,
561 bool with_period);
562static void CloneForeignKeyConstraints(List **wqueue, Relation parentRel,
563 Relation partitionRel);
564static void CloneFkReferenced(Relation parentRel, Relation partitionRel);
565static void CloneFkReferencing(List **wqueue, Relation parentRel,
566 Relation partRel);
567static void createForeignKeyCheckTriggers(Oid myRelOid, Oid refRelOid,
568 Constraint *fkconstraint, Oid constraintOid,
569 Oid indexOid,
570 Oid parentInsTrigger, Oid parentUpdTrigger,
571 Oid *insertTrigOid, Oid *updateTrigOid);
572static void createForeignKeyActionTriggers(Relation rel, Oid refRelOid,
573 Constraint *fkconstraint, Oid constraintOid,
574 Oid indexOid,
575 Oid parentDelTrigger, Oid parentUpdTrigger,
576 Oid *deleteTrigOid, Oid *updateTrigOid);
577static bool tryAttachPartitionForeignKey(List **wqueue,
579 Relation partition,
580 Oid parentConstrOid, int numfks,
581 AttrNumber *mapped_conkey, AttrNumber *confkey,
582 Oid *conpfeqop,
583 Oid parentInsTrigger,
584 Oid parentUpdTrigger,
585 Relation trigrel);
586static void GetForeignKeyActionTriggers(Relation trigrel,
587 Oid conoid, Oid confrelid, Oid conrelid,
588 Oid *deleteTriggerOid,
589 Oid *updateTriggerOid);
590static void GetForeignKeyCheckTriggers(Relation trigrel,
591 Oid conoid, Oid confrelid, Oid conrelid,
592 Oid *insertTriggerOid,
593 Oid *updateTriggerOid);
594static void ATExecDropConstraint(Relation rel, const char *constrName,
595 DropBehavior behavior, bool recurse,
596 bool missing_ok, LOCKMODE lockmode);
598 HeapTuple constraintTup, DropBehavior behavior,
599 bool recurse, bool recursing,
600 bool missing_ok, LOCKMODE lockmode);
601static void ATPrepAlterColumnType(List **wqueue,
602 AlteredTableInfo *tab, Relation rel,
603 bool recurse, bool recursing,
604 AlterTableCmd *cmd, LOCKMODE lockmode,
605 AlterTableUtilityContext *context);
606static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno);
608 AlterTableCmd *cmd, LOCKMODE lockmode);
610 Relation rel, AttrNumber attnum, const char *colName);
612static void RememberIndexForRebuilding(Oid indoid, AlteredTableInfo *tab);
614static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab,
615 LOCKMODE lockmode);
616static void ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId,
617 char *cmd, List **wqueue, LOCKMODE lockmode,
618 bool rewrite);
620 Oid objid, Relation rel, List *domname,
621 const char *conname);
622static void TryReuseIndex(Oid oldId, IndexStmt *stmt);
623static void TryReuseForeignKey(Oid oldId, Constraint *con);
624static ObjectAddress ATExecAlterColumnGenericOptions(Relation rel, const char *colName,
625 List *options, LOCKMODE lockmode);
626static void change_owner_fix_column_acls(Oid relationOid,
627 Oid oldOwnerId, Oid newOwnerId);
628static void change_owner_recurse_to_sequences(Oid relationOid,
629 Oid newOwnerId, LOCKMODE lockmode);
630static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName,
631 LOCKMODE lockmode);
632static void ATExecDropCluster(Relation rel, LOCKMODE lockmode);
633static void ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amname);
634static void ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId);
636 bool toLogged);
637static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
638 const char *tablespacename, LOCKMODE lockmode);
639static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode);
640static void ATExecSetTableSpaceNoStorage(Relation rel, Oid newTableSpace);
641static void ATExecSetRelOptions(Relation rel, List *defList,
642 AlterTableType operation,
643 LOCKMODE lockmode);
644static void ATExecEnableDisableTrigger(Relation rel, const char *trigname,
645 char fires_when, bool skip_system, bool recurse,
646 LOCKMODE lockmode);
647static void ATExecEnableDisableRule(Relation rel, const char *rulename,
648 char fires_when, LOCKMODE lockmode);
649static void ATPrepAddInherit(Relation child_rel);
650static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
651static ObjectAddress ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode);
652static void drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid,
653 DependencyType deptype);
654static ObjectAddress ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode);
655static void ATExecDropOf(Relation rel, LOCKMODE lockmode);
657static void ATExecGenericOptions(Relation rel, List *options);
658static void ATExecSetRowSecurity(Relation rel, bool rls);
659static void ATExecForceNoForceRowSecurity(Relation rel, bool force_rls);
661 const char *column, Node *newValue, LOCKMODE lockmode);
662
663static void index_copy_data(Relation rel, RelFileLocator newrlocator);
664static const char *storage_name(char c);
665
666static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
667 Oid oldRelOid, void *arg);
668static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
669 Oid oldrelid, void *arg);
671static void ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNumber *partattrs,
672 List **partexprs, Oid *partopclass, Oid *partcollation,
673 PartitionStrategy strategy);
674static void CreateInheritance(Relation child_rel, Relation parent_rel, bool ispartition);
675static void RemoveInheritance(Relation child_rel, Relation parent_rel,
676 bool expect_detached);
678 PartitionCmd *cmd,
679 AlterTableUtilityContext *context);
680static void AttachPartitionEnsureIndexes(List **wqueue, Relation rel, Relation attachrel);
681static void QueuePartitionConstraintValidation(List **wqueue, Relation scanrel,
682 List *partConstraint,
683 bool validate_default);
684static void CloneRowTriggersToPartition(Relation parent, Relation partition);
685static void DetachAddConstraintIfNeeded(List **wqueue, Relation partRel);
686static void DropClonedTriggersFromPartition(Oid partitionId);
688 Relation rel, RangeVar *name,
689 bool concurrent);
690static void DetachPartitionFinalize(Relation rel, Relation partRel,
691 bool concurrent, Oid defaultPartOid);
693static ObjectAddress ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx,
694 RangeVar *name);
695static void validatePartitionedIndex(Relation partedIdx, Relation partedTbl);
696static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx,
697 Relation partitionTbl);
698static void verifyPartitionIndexNotNull(IndexInfo *iinfo, Relation partIdx);
699static List *GetParentedForeignKeyRefs(Relation partition);
700static void ATDetachCheckNoForeignKeyRefs(Relation partition);
701static char GetAttributeCompression(Oid atttypid, const char *compression);
702static char GetAttributeStorage(Oid atttypid, const char *storagemode);
703
704
705/* ----------------------------------------------------------------
706 * DefineRelation
707 * Creates a new relation.
708 *
709 * stmt carries parsetree information from an ordinary CREATE TABLE statement.
710 * The other arguments are used to extend the behavior for other cases:
711 * relkind: relkind to assign to the new relation
712 * ownerId: if not InvalidOid, use this as the new relation's owner.
713 * typaddress: if not null, it's set to the pg_type entry's address.
714 * queryString: for error reporting
715 *
716 * Note that permissions checks are done against current user regardless of
717 * ownerId. A nonzero ownerId is used when someone is creating a relation
718 * "on behalf of" someone else, so we still want to see that the current user
719 * has permissions to do it.
720 *
721 * If successful, returns the address of the new relation.
722 * ----------------------------------------------------------------
723 */
725DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
726 ObjectAddress *typaddress, const char *queryString)
727{
728 char relname[NAMEDATALEN];
729 Oid namespaceId;
730 Oid relationId;
731 Oid tablespaceId;
732 Relation rel;
734 List *inheritOids;
735 List *old_constraints;
736 List *old_notnulls;
737 List *rawDefaults;
738 List *cookedDefaults;
739 List *nncols;
740 Datum reloptions;
741 ListCell *listptr;
743 bool partitioned;
744 const char *const validnsps[] = HEAP_RELOPT_NAMESPACES;
745 Oid ofTypeId;
746 ObjectAddress address;
747 LOCKMODE parentLockmode;
748 Oid accessMethodId = InvalidOid;
749
750 /*
751 * Truncate relname to appropriate length (probably a waste of time, as
752 * parser should have done this already).
753 */
754 strlcpy(relname, stmt->relation->relname, NAMEDATALEN);
755
756 /*
757 * Check consistency of arguments
758 */
759 if (stmt->oncommit != ONCOMMIT_NOOP
760 && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
762 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
763 errmsg("ON COMMIT can only be used on temporary tables")));
764
765 if (stmt->partspec != NULL)
766 {
767 if (relkind != RELKIND_RELATION)
768 elog(ERROR, "unexpected relkind: %d", (int) relkind);
769
770 relkind = RELKIND_PARTITIONED_TABLE;
771 partitioned = true;
772 }
773 else
774 partitioned = false;
775
776 if (relkind == RELKIND_PARTITIONED_TABLE &&
777 stmt->relation->relpersistence == RELPERSISTENCE_UNLOGGED)
779 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
780 errmsg("partitioned tables cannot be unlogged")));
781
782 /*
783 * Look up the namespace in which we are supposed to create the relation,
784 * check we have permission to create there, lock it against concurrent
785 * drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary
786 * namespace is selected.
787 */
788 namespaceId =
790
791 /*
792 * Security check: disallow creating temp tables from security-restricted
793 * code. This is needed because calling code might not expect untrusted
794 * tables to appear in pg_temp at the front of its search path.
795 */
796 if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP
799 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
800 errmsg("cannot create temporary table within security-restricted operation")));
801
802 /*
803 * Determine the lockmode to use when scanning parents. A self-exclusive
804 * lock is needed here.
805 *
806 * For regular inheritance, if two backends attempt to add children to the
807 * same parent simultaneously, and that parent has no pre-existing
808 * children, then both will attempt to update the parent's relhassubclass
809 * field, leading to a "tuple concurrently updated" error. Also, this
810 * interlocks against a concurrent ANALYZE on the parent table, which
811 * might otherwise be attempting to clear the parent's relhassubclass
812 * field, if its previous children were recently dropped.
813 *
814 * If the child table is a partition, then we instead grab an exclusive
815 * lock on the parent because its partition descriptor will be changed by
816 * addition of the new partition.
817 */
818 parentLockmode = (stmt->partbound != NULL ? AccessExclusiveLock :
820
821 /* Determine the list of OIDs of the parents. */
822 inheritOids = NIL;
823 foreach(listptr, stmt->inhRelations)
824 {
825 RangeVar *rv = (RangeVar *) lfirst(listptr);
826 Oid parentOid;
827
828 parentOid = RangeVarGetRelid(rv, parentLockmode, false);
829
830 /*
831 * Reject duplications in the list of parents.
832 */
833 if (list_member_oid(inheritOids, parentOid))
835 (errcode(ERRCODE_DUPLICATE_TABLE),
836 errmsg("relation \"%s\" would be inherited from more than once",
837 get_rel_name(parentOid))));
838
839 inheritOids = lappend_oid(inheritOids, parentOid);
840 }
841
842 /*
843 * Select tablespace to use: an explicitly indicated one, or (in the case
844 * of a partitioned table) the parent's, if it has one.
845 */
846 if (stmt->tablespacename)
847 {
848 tablespaceId = get_tablespace_oid(stmt->tablespacename, false);
849
850 if (partitioned && tablespaceId == MyDatabaseTableSpace)
852 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
853 errmsg("cannot specify default tablespace for partitioned relations")));
854 }
855 else if (stmt->partbound)
856 {
857 Assert(list_length(inheritOids) == 1);
858 tablespaceId = get_rel_tablespace(linitial_oid(inheritOids));
859 }
860 else
861 tablespaceId = InvalidOid;
862
863 /* still nothing? use the default */
864 if (!OidIsValid(tablespaceId))
865 tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence,
866 partitioned);
867
868 /* Check permissions except when using database's default */
869 if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
870 {
871 AclResult aclresult;
872
873 aclresult = object_aclcheck(TableSpaceRelationId, tablespaceId, GetUserId(),
874 ACL_CREATE);
875 if (aclresult != ACLCHECK_OK)
877 get_tablespace_name(tablespaceId));
878 }
879
880 /* In all cases disallow placing user relations in pg_global */
881 if (tablespaceId == GLOBALTABLESPACE_OID)
883 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
884 errmsg("only shared relations can be placed in pg_global tablespace")));
885
886 /* Identify user ID that will own the table */
887 if (!OidIsValid(ownerId))
888 ownerId = GetUserId();
889
890 /*
891 * Parse and validate reloptions, if any.
892 */
893 reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
894 true, false);
895
896 switch (relkind)
897 {
898 case RELKIND_VIEW:
899 (void) view_reloptions(reloptions, true);
900 break;
901 case RELKIND_PARTITIONED_TABLE:
902 (void) partitioned_table_reloptions(reloptions, true);
903 break;
904 default:
905 (void) heap_reloptions(relkind, reloptions, true);
906 }
907
908 if (stmt->ofTypename)
909 {
910 AclResult aclresult;
911
912 ofTypeId = typenameTypeId(NULL, stmt->ofTypename);
913
914 aclresult = object_aclcheck(TypeRelationId, ofTypeId, GetUserId(), ACL_USAGE);
915 if (aclresult != ACLCHECK_OK)
916 aclcheck_error_type(aclresult, ofTypeId);
917 }
918 else
919 ofTypeId = InvalidOid;
920
921 /*
922 * Look up inheritance ancestors and generate relation schema, including
923 * inherited attributes. (Note that stmt->tableElts is destructively
924 * modified by MergeAttributes.)
925 */
926 stmt->tableElts =
927 MergeAttributes(stmt->tableElts, inheritOids,
928 stmt->relation->relpersistence,
929 stmt->partbound != NULL,
930 &old_constraints, &old_notnulls);
931
932 /*
933 * Create a tuple descriptor from the relation schema. Note that this
934 * deals with column names, types, and in-descriptor NOT NULL flags, but
935 * not default values, NOT NULL or CHECK constraints; we handle those
936 * below.
937 */
939
940 /*
941 * Find columns with default values and prepare for insertion of the
942 * defaults. Pre-cooked (that is, inherited) defaults go into a list of
943 * CookedConstraint structs that we'll pass to heap_create_with_catalog,
944 * while raw defaults go into a list of RawColumnDefault structs that will
945 * be processed by AddRelationNewConstraints. (We can't deal with raw
946 * expressions until we can do transformExpr.)
947 *
948 * We can set the atthasdef flags now in the tuple descriptor; this just
949 * saves StoreAttrDefault from having to do an immediate update of the
950 * pg_attribute rows.
951 */
952 rawDefaults = NIL;
953 cookedDefaults = NIL;
954 attnum = 0;
955
956 foreach(listptr, stmt->tableElts)
957 {
958 ColumnDef *colDef = lfirst(listptr);
960
961 attnum++;
962 attr = TupleDescAttr(descriptor, attnum - 1);
963
964 if (colDef->raw_default != NULL)
965 {
966 RawColumnDefault *rawEnt;
967
968 Assert(colDef->cooked_default == NULL);
969
970 rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
971 rawEnt->attnum = attnum;
972 rawEnt->raw_default = colDef->raw_default;
973 rawEnt->missingMode = false;
974 rawEnt->generated = colDef->generated;
975 rawDefaults = lappend(rawDefaults, rawEnt);
976 attr->atthasdef = true;
977 }
978 else if (colDef->cooked_default != NULL)
979 {
980 CookedConstraint *cooked;
981
982 cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
983 cooked->contype = CONSTR_DEFAULT;
984 cooked->conoid = InvalidOid; /* until created */
985 cooked->name = NULL;
986 cooked->attnum = attnum;
987 cooked->expr = colDef->cooked_default;
988 cooked->is_enforced = true;
989 cooked->skip_validation = false;
990 cooked->is_local = true; /* not used for defaults */
991 cooked->inhcount = 0; /* ditto */
992 cooked->is_no_inherit = false;
993 cookedDefaults = lappend(cookedDefaults, cooked);
994 attr->atthasdef = true;
995 }
996
998 }
999
1000 /*
1001 * For relations with table AM and partitioned tables, select access
1002 * method to use: an explicitly indicated one, or (in the case of a
1003 * partitioned table) the parent's, if it has one.
1004 */
1005 if (stmt->accessMethod != NULL)
1006 {
1007 Assert(RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE);
1008 accessMethodId = get_table_am_oid(stmt->accessMethod, false);
1009 }
1010 else if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE)
1011 {
1012 if (stmt->partbound)
1013 {
1014 Assert(list_length(inheritOids) == 1);
1015 accessMethodId = get_rel_relam(linitial_oid(inheritOids));
1016 }
1017
1018 if (RELKIND_HAS_TABLE_AM(relkind) && !OidIsValid(accessMethodId))
1019 accessMethodId = get_table_am_oid(default_table_access_method, false);
1020 }
1021
1022 /*
1023 * Create the relation. Inherited defaults and CHECK constraints are
1024 * passed in for immediate handling --- since they don't need parsing,
1025 * they can be stored immediately.
1026 */
1027 relationId = heap_create_with_catalog(relname,
1028 namespaceId,
1029 tablespaceId,
1030 InvalidOid,
1031 InvalidOid,
1032 ofTypeId,
1033 ownerId,
1034 accessMethodId,
1035 descriptor,
1036 list_concat(cookedDefaults,
1037 old_constraints),
1038 relkind,
1039 stmt->relation->relpersistence,
1040 false,
1041 false,
1042 stmt->oncommit,
1043 reloptions,
1044 true,
1046 false,
1047 InvalidOid,
1048 typaddress);
1049
1050 /*
1051 * We must bump the command counter to make the newly-created relation
1052 * tuple visible for opening.
1053 */
1055
1056 /*
1057 * Open the new relation and acquire exclusive lock on it. This isn't
1058 * really necessary for locking out other backends (since they can't see
1059 * the new rel anyway until we commit), but it keeps the lock manager from
1060 * complaining about deadlock risks.
1061 */
1062 rel = relation_open(relationId, AccessExclusiveLock);
1063
1064 /*
1065 * Now add any newly specified column default and generation expressions
1066 * to the new relation. These are passed to us in the form of raw
1067 * parsetrees; we need to transform them to executable expression trees
1068 * before they can be added. The most convenient way to do that is to
1069 * apply the parser's transformExpr routine, but transformExpr doesn't
1070 * work unless we have a pre-existing relation. So, the transformation has
1071 * to be postponed to this final step of CREATE TABLE.
1072 *
1073 * This needs to be before processing the partitioning clauses because
1074 * those could refer to generated columns.
1075 */
1076 if (rawDefaults)
1077 AddRelationNewConstraints(rel, rawDefaults, NIL,
1078 true, true, false, queryString);
1079
1080 /*
1081 * Make column generation expressions visible for use by partitioning.
1082 */
1084
1085 /* Process and store partition bound, if any. */
1086 if (stmt->partbound)
1087 {
1088 PartitionBoundSpec *bound;
1089 ParseState *pstate;
1090 Oid parentId = linitial_oid(inheritOids),
1091 defaultPartOid;
1092 Relation parent,
1093 defaultRel = NULL;
1094 ParseNamespaceItem *nsitem;
1095
1096 /* Already have strong enough lock on the parent */
1097 parent = table_open(parentId, NoLock);
1098
1099 /*
1100 * We are going to try to validate the partition bound specification
1101 * against the partition key of parentRel, so it better have one.
1102 */
1103 if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1104 ereport(ERROR,
1105 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1106 errmsg("\"%s\" is not partitioned",
1107 RelationGetRelationName(parent))));
1108
1109 /*
1110 * The partition constraint of the default partition depends on the
1111 * partition bounds of every other partition. It is possible that
1112 * another backend might be about to execute a query on the default
1113 * partition table, and that the query relies on previously cached
1114 * default partition constraints. We must therefore take a table lock
1115 * strong enough to prevent all queries on the default partition from
1116 * proceeding until we commit and send out a shared-cache-inval notice
1117 * that will make them update their index lists.
1118 *
1119 * Order of locking: The relation being added won't be visible to
1120 * other backends until it is committed, hence here in
1121 * DefineRelation() the order of locking the default partition and the
1122 * relation being added does not matter. But at all other places we
1123 * need to lock the default relation before we lock the relation being
1124 * added or removed i.e. we should take the lock in same order at all
1125 * the places such that lock parent, lock default partition and then
1126 * lock the partition so as to avoid a deadlock.
1127 */
1128 defaultPartOid =
1130 true));
1131 if (OidIsValid(defaultPartOid))
1132 defaultRel = table_open(defaultPartOid, AccessExclusiveLock);
1133
1134 /* Transform the bound values */
1135 pstate = make_parsestate(NULL);
1136 pstate->p_sourcetext = queryString;
1137
1138 /*
1139 * Add an nsitem containing this relation, so that transformExpr
1140 * called on partition bound expressions is able to report errors
1141 * using a proper context.
1142 */
1143 nsitem = addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
1144 NULL, false, false);
1145 addNSItemToQuery(pstate, nsitem, false, true, true);
1146
1147 bound = transformPartitionBound(pstate, parent, stmt->partbound);
1148
1149 /*
1150 * Check first that the new partition's bound is valid and does not
1151 * overlap with any of existing partitions of the parent.
1152 */
1153 check_new_partition_bound(relname, parent, bound, pstate);
1154
1155 /*
1156 * If the default partition exists, its partition constraints will
1157 * change after the addition of this new partition such that it won't
1158 * allow any row that qualifies for this new partition. So, check that
1159 * the existing data in the default partition satisfies the constraint
1160 * as it will exist after adding this partition.
1161 */
1162 if (OidIsValid(defaultPartOid))
1163 {
1164 check_default_partition_contents(parent, defaultRel, bound);
1165 /* Keep the lock until commit. */
1166 table_close(defaultRel, NoLock);
1167 }
1168
1169 /* Update the pg_class entry. */
1170 StorePartitionBound(rel, parent, bound);
1171
1172 table_close(parent, NoLock);
1173 }
1174
1175 /* Store inheritance information for new rel. */
1176 StoreCatalogInheritance(relationId, inheritOids, stmt->partbound != NULL);
1177
1178 /*
1179 * Process the partitioning specification (if any) and store the partition
1180 * key information into the catalog.
1181 */
1182 if (partitioned)
1183 {
1184 ParseState *pstate;
1185 int partnatts;
1186 AttrNumber partattrs[PARTITION_MAX_KEYS];
1187 Oid partopclass[PARTITION_MAX_KEYS];
1188 Oid partcollation[PARTITION_MAX_KEYS];
1189 List *partexprs = NIL;
1190
1191 pstate = make_parsestate(NULL);
1192 pstate->p_sourcetext = queryString;
1193
1194 partnatts = list_length(stmt->partspec->partParams);
1195
1196 /* Protect fixed-size arrays here and in executor */
1197 if (partnatts > PARTITION_MAX_KEYS)
1198 ereport(ERROR,
1199 (errcode(ERRCODE_TOO_MANY_COLUMNS),
1200 errmsg("cannot partition using more than %d columns",
1202
1203 /*
1204 * We need to transform the raw parsetrees corresponding to partition
1205 * expressions into executable expression trees. Like column defaults
1206 * and CHECK constraints, we could not have done the transformation
1207 * earlier.
1208 */
1209 stmt->partspec = transformPartitionSpec(rel, stmt->partspec);
1210
1211 ComputePartitionAttrs(pstate, rel, stmt->partspec->partParams,
1212 partattrs, &partexprs, partopclass,
1213 partcollation, stmt->partspec->strategy);
1214
1215 StorePartitionKey(rel, stmt->partspec->strategy, partnatts, partattrs,
1216 partexprs,
1217 partopclass, partcollation);
1218
1219 /* make it all visible */
1221 }
1222
1223 /*
1224 * If we're creating a partition, create now all the indexes, triggers,
1225 * FKs defined in the parent.
1226 *
1227 * We can't do it earlier, because DefineIndex wants to know the partition
1228 * key which we just stored.
1229 */
1230 if (stmt->partbound)
1231 {
1232 Oid parentId = linitial_oid(inheritOids);
1233 Relation parent;
1234 List *idxlist;
1235 ListCell *cell;
1236
1237 /* Already have strong enough lock on the parent */
1238 parent = table_open(parentId, NoLock);
1239 idxlist = RelationGetIndexList(parent);
1240
1241 /*
1242 * For each index in the parent table, create one in the partition
1243 */
1244 foreach(cell, idxlist)
1245 {
1247 AttrMap *attmap;
1248 IndexStmt *idxstmt;
1249 Oid constraintOid;
1250
1251 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1252 {
1253 if (idxRel->rd_index->indisunique)
1254 ereport(ERROR,
1255 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1256 errmsg("cannot create foreign partition of partitioned table \"%s\"",
1257 RelationGetRelationName(parent)),
1258 errdetail("Table \"%s\" contains indexes that are unique.",
1259 RelationGetRelationName(parent))));
1260 else
1261 {
1263 continue;
1264 }
1265 }
1266
1268 RelationGetDescr(parent),
1269 false);
1270 idxstmt =
1271 generateClonedIndexStmt(NULL, idxRel,
1272 attmap, &constraintOid);
1274 idxstmt,
1275 InvalidOid,
1276 RelationGetRelid(idxRel),
1277 constraintOid,
1278 -1,
1279 false, false, false, false, false);
1280
1282 }
1283
1284 list_free(idxlist);
1285
1286 /*
1287 * If there are any row-level triggers, clone them to the new
1288 * partition.
1289 */
1290 if (parent->trigdesc != NULL)
1291 CloneRowTriggersToPartition(parent, rel);
1292
1293 /*
1294 * And foreign keys too. Note that because we're freshly creating the
1295 * table, there is no need to verify these new constraints.
1296 */
1297 CloneForeignKeyConstraints(NULL, parent, rel);
1298
1299 table_close(parent, NoLock);
1300 }
1301
1302 /*
1303 * Now add any newly specified CHECK constraints to the new relation. Same
1304 * as for defaults above, but these need to come after partitioning is set
1305 * up.
1306 */
1307 if (stmt->constraints)
1308 AddRelationNewConstraints(rel, NIL, stmt->constraints,
1309 true, true, false, queryString);
1310
1311 /*
1312 * Finally, merge the not-null constraints that are declared directly with
1313 * those that come from parent relations (making sure to count inheritance
1314 * appropriately for each), create them, and set the attnotnull flag on
1315 * columns that don't yet have it.
1316 */
1317 nncols = AddRelationNotNullConstraints(rel, stmt->nnconstraints,
1318 old_notnulls);
1319 foreach_int(attrnum, nncols)
1320 set_attnotnull(NULL, rel, attrnum, NoLock);
1321
1322 ObjectAddressSet(address, RelationRelationId, relationId);
1323
1324 /*
1325 * Clean up. We keep lock on new relation (although it shouldn't be
1326 * visible to anyone else anyway, until commit).
1327 */
1328 relation_close(rel, NoLock);
1329
1330 return address;
1331}
1332
1333/*
1334 * BuildDescForRelation
1335 *
1336 * Given a list of ColumnDef nodes, build a TupleDesc.
1337 *
1338 * Note: This is only for the limited purpose of table and view creation. Not
1339 * everything is filled in. A real tuple descriptor should be obtained from
1340 * the relcache.
1341 */
1344{
1345 int natts;
1347 ListCell *l;
1348 TupleDesc desc;
1349 char *attname;
1350 Oid atttypid;
1351 int32 atttypmod;
1352 Oid attcollation;
1353 int attdim;
1354
1355 /*
1356 * allocate a new tuple descriptor
1357 */
1358 natts = list_length(columns);
1359 desc = CreateTemplateTupleDesc(natts);
1360
1361 attnum = 0;
1362
1363 foreach(l, columns)
1364 {
1365 ColumnDef *entry = lfirst(l);
1366 AclResult aclresult;
1368
1369 /*
1370 * for each entry in the list, get the name and type information from
1371 * the list and have TupleDescInitEntry fill in the attribute
1372 * information we need.
1373 */
1374 attnum++;
1375
1376 attname = entry->colname;
1377 typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
1378
1379 aclresult = object_aclcheck(TypeRelationId, atttypid, GetUserId(), ACL_USAGE);
1380 if (aclresult != ACLCHECK_OK)
1381 aclcheck_error_type(aclresult, atttypid);
1382
1383 attcollation = GetColumnDefCollation(NULL, entry, atttypid);
1384 attdim = list_length(entry->typeName->arrayBounds);
1385 if (attdim > PG_INT16_MAX)
1386 ereport(ERROR,
1387 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1388 errmsg("too many array dimensions"));
1389
1390 if (entry->typeName->setof)
1391 ereport(ERROR,
1392 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
1393 errmsg("column \"%s\" cannot be declared SETOF",
1394 attname)));
1395
1397 atttypid, atttypmod, attdim);
1398 att = TupleDescAttr(desc, attnum - 1);
1399
1400 /* Override TupleDescInitEntry's settings as requested */
1401 TupleDescInitEntryCollation(desc, attnum, attcollation);
1402
1403 /* Fill in additional stuff not handled by TupleDescInitEntry */
1404 att->attnotnull = entry->is_not_null;
1405 att->attislocal = entry->is_local;
1406 att->attinhcount = entry->inhcount;
1407 att->attidentity = entry->identity;
1408 att->attgenerated = entry->generated;
1409 att->attcompression = GetAttributeCompression(att->atttypid, entry->compression);
1410 if (entry->storage)
1411 att->attstorage = entry->storage;
1412 else if (entry->storage_name)
1413 att->attstorage = GetAttributeStorage(att->atttypid, entry->storage_name);
1414
1416 }
1417
1418 return desc;
1419}
1420
1421/*
1422 * Emit the right error or warning message for a "DROP" command issued on a
1423 * non-existent relation
1424 */
1425static void
1426DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
1427{
1428 const struct dropmsgstrings *rentry;
1429
1430 if (rel->schemaname != NULL &&
1432 {
1433 if (!missing_ok)
1434 {
1435 ereport(ERROR,
1436 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1437 errmsg("schema \"%s\" does not exist", rel->schemaname)));
1438 }
1439 else
1440 {
1442 (errmsg("schema \"%s\" does not exist, skipping",
1443 rel->schemaname)));
1444 }
1445 return;
1446 }
1447
1448 for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
1449 {
1450 if (rentry->kind == rightkind)
1451 {
1452 if (!missing_ok)
1453 {
1454 ereport(ERROR,
1455 (errcode(rentry->nonexistent_code),
1456 errmsg(rentry->nonexistent_msg, rel->relname)));
1457 }
1458 else
1459 {
1460 ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
1461 break;
1462 }
1463 }
1464 }
1465
1466 Assert(rentry->kind != '\0'); /* Should be impossible */
1467}
1468
1469/*
1470 * Emit the right error message for a "DROP" command issued on a
1471 * relation of the wrong type
1472 */
1473static void
1474DropErrorMsgWrongType(const char *relname, char wrongkind, char rightkind)
1475{
1476 const struct dropmsgstrings *rentry;
1477 const struct dropmsgstrings *wentry;
1478
1479 for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
1480 if (rentry->kind == rightkind)
1481 break;
1482 Assert(rentry->kind != '\0');
1483
1484 for (wentry = dropmsgstringarray; wentry->kind != '\0'; wentry++)
1485 if (wentry->kind == wrongkind)
1486 break;
1487 /* wrongkind could be something we don't have in our table... */
1488
1489 ereport(ERROR,
1490 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1491 errmsg(rentry->nota_msg, relname),
1492 (wentry->kind != '\0') ? errhint("%s", _(wentry->drophint_msg)) : 0));
1493}
1494
1495/*
1496 * RemoveRelations
1497 * Implements DROP TABLE, DROP INDEX, DROP SEQUENCE, DROP VIEW,
1498 * DROP MATERIALIZED VIEW, DROP FOREIGN TABLE
1499 */
1500void
1502{
1503 ObjectAddresses *objects;
1504 char relkind;
1505 ListCell *cell;
1506 int flags = 0;
1507 LOCKMODE lockmode = AccessExclusiveLock;
1508
1509 /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
1510 if (drop->concurrent)
1511 {
1512 /*
1513 * Note that for temporary relations this lock may get upgraded later
1514 * on, but as no other session can access a temporary relation, this
1515 * is actually fine.
1516 */
1517 lockmode = ShareUpdateExclusiveLock;
1518 Assert(drop->removeType == OBJECT_INDEX);
1519 if (list_length(drop->objects) != 1)
1520 ereport(ERROR,
1521 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1522 errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects")));
1523 if (drop->behavior == DROP_CASCADE)
1524 ereport(ERROR,
1525 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1526 errmsg("DROP INDEX CONCURRENTLY does not support CASCADE")));
1527 }
1528
1529 /*
1530 * First we identify all the relations, then we delete them in a single
1531 * performMultipleDeletions() call. This is to avoid unwanted DROP
1532 * RESTRICT errors if one of the relations depends on another.
1533 */
1534
1535 /* Determine required relkind */
1536 switch (drop->removeType)
1537 {
1538 case OBJECT_TABLE:
1539 relkind = RELKIND_RELATION;
1540 break;
1541
1542 case OBJECT_INDEX:
1543 relkind = RELKIND_INDEX;
1544 break;
1545
1546 case OBJECT_SEQUENCE:
1547 relkind = RELKIND_SEQUENCE;
1548 break;
1549
1550 case OBJECT_VIEW:
1551 relkind = RELKIND_VIEW;
1552 break;
1553
1554 case OBJECT_MATVIEW:
1555 relkind = RELKIND_MATVIEW;
1556 break;
1557
1559 relkind = RELKIND_FOREIGN_TABLE;
1560 break;
1561
1562 default:
1563 elog(ERROR, "unrecognized drop object type: %d",
1564 (int) drop->removeType);
1565 relkind = 0; /* keep compiler quiet */
1566 break;
1567 }
1568
1569 /* Lock and validate each relation; build a list of object addresses */
1570 objects = new_object_addresses();
1571
1572 foreach(cell, drop->objects)
1573 {
1574 RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell));
1575 Oid relOid;
1576 ObjectAddress obj;
1578
1579 /*
1580 * These next few steps are a great deal like relation_openrv, but we
1581 * don't bother building a relcache entry since we don't need it.
1582 *
1583 * Check for shared-cache-inval messages before trying to access the
1584 * relation. This is needed to cover the case where the name
1585 * identifies a rel that has been dropped and recreated since the
1586 * start of our transaction: if we don't flush the old syscache entry,
1587 * then we'll latch onto that entry and suffer an error later.
1588 */
1590
1591 /* Look up the appropriate relation using namespace search. */
1592 state.expected_relkind = relkind;
1593 state.heap_lockmode = drop->concurrent ?
1595 /* We must initialize these fields to show that no locks are held: */
1596 state.heapOid = InvalidOid;
1597 state.partParentOid = InvalidOid;
1598
1599 relOid = RangeVarGetRelidExtended(rel, lockmode, RVR_MISSING_OK,
1601 &state);
1602
1603 /* Not there? */
1604 if (!OidIsValid(relOid))
1605 {
1606 DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
1607 continue;
1608 }
1609
1610 /*
1611 * Decide if concurrent mode needs to be used here or not. The
1612 * callback retrieved the rel's persistence for us.
1613 */
1614 if (drop->concurrent &&
1615 state.actual_relpersistence != RELPERSISTENCE_TEMP)
1616 {
1617 Assert(list_length(drop->objects) == 1 &&
1618 drop->removeType == OBJECT_INDEX);
1620 }
1621
1622 /*
1623 * Concurrent index drop cannot be used with partitioned indexes,
1624 * either.
1625 */
1626 if ((flags & PERFORM_DELETION_CONCURRENTLY) != 0 &&
1627 state.actual_relkind == RELKIND_PARTITIONED_INDEX)
1628 ereport(ERROR,
1629 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1630 errmsg("cannot drop partitioned index \"%s\" concurrently",
1631 rel->relname)));
1632
1633 /*
1634 * If we're told to drop a partitioned index, we must acquire lock on
1635 * all the children of its parent partitioned table before proceeding.
1636 * Otherwise we'd try to lock the child index partitions before their
1637 * tables, leading to potential deadlock against other sessions that
1638 * will lock those objects in the other order.
1639 */
1640 if (state.actual_relkind == RELKIND_PARTITIONED_INDEX)
1641 (void) find_all_inheritors(state.heapOid,
1642 state.heap_lockmode,
1643 NULL);
1644
1645 /* OK, we're ready to delete this one */
1646 obj.classId = RelationRelationId;
1647 obj.objectId = relOid;
1648 obj.objectSubId = 0;
1649
1650 add_exact_object_address(&obj, objects);
1651 }
1652
1653 performMultipleDeletions(objects, drop->behavior, flags);
1654
1655 free_object_addresses(objects);
1656}
1657
1658/*
1659 * Before acquiring a table lock, check whether we have sufficient rights.
1660 * In the case of DROP INDEX, also try to lock the table before the index.
1661 * Also, if the table to be dropped is a partition, we try to lock the parent
1662 * first.
1663 */
1664static void
1665RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
1666 void *arg)
1667{
1668 HeapTuple tuple;
1670 char expected_relkind;
1671 bool is_partition;
1672 Form_pg_class classform;
1674 bool invalid_system_index = false;
1675
1676 state = (struct DropRelationCallbackState *) arg;
1677 heap_lockmode = state->heap_lockmode;
1678
1679 /*
1680 * If we previously locked some other index's heap, and the name we're
1681 * looking up no longer refers to that relation, release the now-useless
1682 * lock.
1683 */
1684 if (relOid != oldRelOid && OidIsValid(state->heapOid))
1685 {
1687 state->heapOid = InvalidOid;
1688 }
1689
1690 /*
1691 * Similarly, if we previously locked some other partition's heap, and the
1692 * name we're looking up no longer refers to that relation, release the
1693 * now-useless lock.
1694 */
1695 if (relOid != oldRelOid && OidIsValid(state->partParentOid))
1696 {
1698 state->partParentOid = InvalidOid;
1699 }
1700
1701 /* Didn't find a relation, so no need for locking or permission checks. */
1702 if (!OidIsValid(relOid))
1703 return;
1704
1705 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
1706 if (!HeapTupleIsValid(tuple))
1707 return; /* concurrently dropped, so nothing to do */
1708 classform = (Form_pg_class) GETSTRUCT(tuple);
1709 is_partition = classform->relispartition;
1710
1711 /* Pass back some data to save lookups in RemoveRelations */
1712 state->actual_relkind = classform->relkind;
1713 state->actual_relpersistence = classform->relpersistence;
1714
1715 /*
1716 * Both RELKIND_RELATION and RELKIND_PARTITIONED_TABLE are OBJECT_TABLE,
1717 * but RemoveRelations() can only pass one relkind for a given relation.
1718 * It chooses RELKIND_RELATION for both regular and partitioned tables.
1719 * That means we must be careful before giving the wrong type error when
1720 * the relation is RELKIND_PARTITIONED_TABLE. An equivalent problem
1721 * exists with indexes.
1722 */
1723 if (classform->relkind == RELKIND_PARTITIONED_TABLE)
1724 expected_relkind = RELKIND_RELATION;
1725 else if (classform->relkind == RELKIND_PARTITIONED_INDEX)
1726 expected_relkind = RELKIND_INDEX;
1727 else
1728 expected_relkind = classform->relkind;
1729
1730 if (state->expected_relkind != expected_relkind)
1731 DropErrorMsgWrongType(rel->relname, classform->relkind,
1732 state->expected_relkind);
1733
1734 /* Allow DROP to either table owner or schema owner */
1735 if (!object_ownercheck(RelationRelationId, relOid, GetUserId()) &&
1736 !object_ownercheck(NamespaceRelationId, classform->relnamespace, GetUserId()))
1738 get_relkind_objtype(classform->relkind),
1739 rel->relname);
1740
1741 /*
1742 * Check the case of a system index that might have been invalidated by a
1743 * failed concurrent process and allow its drop. For the time being, this
1744 * only concerns indexes of toast relations that became invalid during a
1745 * REINDEX CONCURRENTLY process.
1746 */
1747 if (IsSystemClass(relOid, classform) && classform->relkind == RELKIND_INDEX)
1748 {
1749 HeapTuple locTuple;
1750 Form_pg_index indexform;
1751 bool indisvalid;
1752
1753 locTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(relOid));
1754 if (!HeapTupleIsValid(locTuple))
1755 {
1756 ReleaseSysCache(tuple);
1757 return;
1758 }
1759
1760 indexform = (Form_pg_index) GETSTRUCT(locTuple);
1761 indisvalid = indexform->indisvalid;
1762 ReleaseSysCache(locTuple);
1763
1764 /* Mark object as being an invalid index of system catalogs */
1765 if (!indisvalid)
1766 invalid_system_index = true;
1767 }
1768
1769 /* In the case of an invalid index, it is fine to bypass this check */
1770 if (!invalid_system_index && !allowSystemTableMods && IsSystemClass(relOid, classform))
1771 ereport(ERROR,
1772 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1773 errmsg("permission denied: \"%s\" is a system catalog",
1774 rel->relname)));
1775
1776 ReleaseSysCache(tuple);
1777
1778 /*
1779 * In DROP INDEX, attempt to acquire lock on the parent table before
1780 * locking the index. index_drop() will need this anyway, and since
1781 * regular queries lock tables before their indexes, we risk deadlock if
1782 * we do it the other way around. No error if we don't find a pg_index
1783 * entry, though --- the relation may have been dropped. Note that this
1784 * code will execute for either plain or partitioned indexes.
1785 */
1786 if (expected_relkind == RELKIND_INDEX &&
1787 relOid != oldRelOid)
1788 {
1789 state->heapOid = IndexGetRelation(relOid, true);
1790 if (OidIsValid(state->heapOid))
1792 }
1793
1794 /*
1795 * Similarly, if the relation is a partition, we must acquire lock on its
1796 * parent before locking the partition. That's because queries lock the
1797 * parent before its partitions, so we risk deadlock if we do it the other
1798 * way around.
1799 */
1800 if (is_partition && relOid != oldRelOid)
1801 {
1802 state->partParentOid = get_partition_parent(relOid, true);
1803 if (OidIsValid(state->partParentOid))
1804 LockRelationOid(state->partParentOid, AccessExclusiveLock);
1805 }
1806}
1807
1808/*
1809 * ExecuteTruncate
1810 * Executes a TRUNCATE command.
1811 *
1812 * This is a multi-relation truncate. We first open and grab exclusive
1813 * lock on all relations involved, checking permissions and otherwise
1814 * verifying that the relation is OK for truncation. Note that if relations
1815 * are foreign tables, at this stage, we have not yet checked that their
1816 * foreign data in external data sources are OK for truncation. These are
1817 * checked when foreign data are actually truncated later. In CASCADE mode,
1818 * relations having FK references to the targeted relations are automatically
1819 * added to the group; in RESTRICT mode, we check that all FK references are
1820 * internal to the group that's being truncated. Finally all the relations
1821 * are truncated and reindexed.
1822 */
1823void
1825{
1826 List *rels = NIL;
1827 List *relids = NIL;
1828 List *relids_logged = NIL;
1829 ListCell *cell;
1830
1831 /*
1832 * Open, exclusive-lock, and check all the explicitly-specified relations
1833 */
1834 foreach(cell, stmt->relations)
1835 {
1836 RangeVar *rv = lfirst(cell);
1837 Relation rel;
1838 bool recurse = rv->inh;
1839 Oid myrelid;
1840 LOCKMODE lockmode = AccessExclusiveLock;
1841
1842 myrelid = RangeVarGetRelidExtended(rv, lockmode,
1844 NULL);
1845
1846 /* don't throw error for "TRUNCATE foo, foo" */
1847 if (list_member_oid(relids, myrelid))
1848 continue;
1849
1850 /* open the relation, we already hold a lock on it */
1851 rel = table_open(myrelid, NoLock);
1852
1853 /*
1854 * RangeVarGetRelidExtended() has done most checks with its callback,
1855 * but other checks with the now-opened Relation remain.
1856 */
1858
1859 rels = lappend(rels, rel);
1860 relids = lappend_oid(relids, myrelid);
1861
1862 /* Log this relation only if needed for logical decoding */
1864 relids_logged = lappend_oid(relids_logged, myrelid);
1865
1866 if (recurse)
1867 {
1868 ListCell *child;
1869 List *children;
1870
1871 children = find_all_inheritors(myrelid, lockmode, NULL);
1872
1873 foreach(child, children)
1874 {
1875 Oid childrelid = lfirst_oid(child);
1876
1877 if (list_member_oid(relids, childrelid))
1878 continue;
1879
1880 /* find_all_inheritors already got lock */
1881 rel = table_open(childrelid, NoLock);
1882
1883 /*
1884 * It is possible that the parent table has children that are
1885 * temp tables of other backends. We cannot safely access
1886 * such tables (because of buffering issues), and the best
1887 * thing to do is to silently ignore them. Note that this
1888 * check is the same as one of the checks done in
1889 * truncate_check_activity() called below, still it is kept
1890 * here for simplicity.
1891 */
1892 if (RELATION_IS_OTHER_TEMP(rel))
1893 {
1894 table_close(rel, lockmode);
1895 continue;
1896 }
1897
1898 /*
1899 * Inherited TRUNCATE commands perform access permission
1900 * checks on the parent table only. So we skip checking the
1901 * children's permissions and don't call
1902 * truncate_check_perms() here.
1903 */
1906
1907 rels = lappend(rels, rel);
1908 relids = lappend_oid(relids, childrelid);
1909
1910 /* Log this relation only if needed for logical decoding */
1912 relids_logged = lappend_oid(relids_logged, childrelid);
1913 }
1914 }
1915 else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1916 ereport(ERROR,
1917 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1918 errmsg("cannot truncate only a partitioned table"),
1919 errhint("Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.")));
1920 }
1921
1922 ExecuteTruncateGuts(rels, relids, relids_logged,
1923 stmt->behavior, stmt->restart_seqs, false);
1924
1925 /* And close the rels */
1926 foreach(cell, rels)
1927 {
1928 Relation rel = (Relation) lfirst(cell);
1929
1930 table_close(rel, NoLock);
1931 }
1932}
1933
1934/*
1935 * ExecuteTruncateGuts
1936 *
1937 * Internal implementation of TRUNCATE. This is called by the actual TRUNCATE
1938 * command (see above) as well as replication subscribers that execute a
1939 * replicated TRUNCATE action.
1940 *
1941 * explicit_rels is the list of Relations to truncate that the command
1942 * specified. relids is the list of Oids corresponding to explicit_rels.
1943 * relids_logged is the list of Oids (a subset of relids) that require
1944 * WAL-logging. This is all a bit redundant, but the existing callers have
1945 * this information handy in this form.
1946 */
1947void
1949 List *relids,
1950 List *relids_logged,
1951 DropBehavior behavior, bool restart_seqs,
1952 bool run_as_table_owner)
1953{
1954 List *rels;
1955 List *seq_relids = NIL;
1956 HTAB *ft_htab = NULL;
1957 EState *estate;
1958 ResultRelInfo *resultRelInfos;
1959 ResultRelInfo *resultRelInfo;
1960 SubTransactionId mySubid;
1961 ListCell *cell;
1962 Oid *logrelids;
1963
1964 /*
1965 * Check the explicitly-specified relations.
1966 *
1967 * In CASCADE mode, suck in all referencing relations as well. This
1968 * requires multiple iterations to find indirectly-dependent relations. At
1969 * each phase, we need to exclusive-lock new rels before looking for their
1970 * dependencies, else we might miss something. Also, we check each rel as
1971 * soon as we open it, to avoid a faux pas such as holding lock for a long
1972 * time on a rel we have no permissions for.
1973 */
1974 rels = list_copy(explicit_rels);
1975 if (behavior == DROP_CASCADE)
1976 {
1977 for (;;)
1978 {
1979 List *newrelids;
1980
1981 newrelids = heap_truncate_find_FKs(relids);
1982 if (newrelids == NIL)
1983 break; /* nothing else to add */
1984
1985 foreach(cell, newrelids)
1986 {
1987 Oid relid = lfirst_oid(cell);
1988 Relation rel;
1989
1990 rel = table_open(relid, AccessExclusiveLock);
1992 (errmsg("truncate cascades to table \"%s\"",
1994 truncate_check_rel(relid, rel->rd_rel);
1995 truncate_check_perms(relid, rel->rd_rel);
1997 rels = lappend(rels, rel);
1998 relids = lappend_oid(relids, relid);
1999
2000 /* Log this relation only if needed for logical decoding */
2002 relids_logged = lappend_oid(relids_logged, relid);
2003 }
2004 }
2005 }
2006
2007 /*
2008 * Check foreign key references. In CASCADE mode, this should be
2009 * unnecessary since we just pulled in all the references; but as a
2010 * cross-check, do it anyway if in an Assert-enabled build.
2011 */
2012#ifdef USE_ASSERT_CHECKING
2013 heap_truncate_check_FKs(rels, false);
2014#else
2015 if (behavior == DROP_RESTRICT)
2016 heap_truncate_check_FKs(rels, false);
2017#endif
2018
2019 /*
2020 * If we are asked to restart sequences, find all the sequences, lock them
2021 * (we need AccessExclusiveLock for ResetSequence), and check permissions.
2022 * We want to do this early since it's pointless to do all the truncation
2023 * work only to fail on sequence permissions.
2024 */
2025 if (restart_seqs)
2026 {
2027 foreach(cell, rels)
2028 {
2029 Relation rel = (Relation) lfirst(cell);
2030 List *seqlist = getOwnedSequences(RelationGetRelid(rel));
2031 ListCell *seqcell;
2032
2033 foreach(seqcell, seqlist)
2034 {
2035 Oid seq_relid = lfirst_oid(seqcell);
2036 Relation seq_rel;
2037
2038 seq_rel = relation_open(seq_relid, AccessExclusiveLock);
2039
2040 /* This check must match AlterSequence! */
2041 if (!object_ownercheck(RelationRelationId, seq_relid, GetUserId()))
2043 RelationGetRelationName(seq_rel));
2044
2045 seq_relids = lappend_oid(seq_relids, seq_relid);
2046
2047 relation_close(seq_rel, NoLock);
2048 }
2049 }
2050 }
2051
2052 /* Prepare to catch AFTER triggers. */
2054
2055 /*
2056 * To fire triggers, we'll need an EState as well as a ResultRelInfo for
2057 * each relation. We don't need to call ExecOpenIndices, though.
2058 *
2059 * We put the ResultRelInfos in the es_opened_result_relations list, even
2060 * though we don't have a range table and don't populate the
2061 * es_result_relations array. That's a bit bogus, but it's enough to make
2062 * ExecGetTriggerResultRel() find them.
2063 */
2064 estate = CreateExecutorState();
2065 resultRelInfos = (ResultRelInfo *)
2066 palloc(list_length(rels) * sizeof(ResultRelInfo));
2067 resultRelInfo = resultRelInfos;
2068 foreach(cell, rels)
2069 {
2070 Relation rel = (Relation) lfirst(cell);
2071
2072 InitResultRelInfo(resultRelInfo,
2073 rel,
2074 0, /* dummy rangetable index */
2075 NULL,
2076 0);
2078 lappend(estate->es_opened_result_relations, resultRelInfo);
2079 resultRelInfo++;
2080 }
2081
2082 /*
2083 * Process all BEFORE STATEMENT TRUNCATE triggers before we begin
2084 * truncating (this is because one of them might throw an error). Also, if
2085 * we were to allow them to prevent statement execution, that would need
2086 * to be handled here.
2087 */
2088 resultRelInfo = resultRelInfos;
2089 foreach(cell, rels)
2090 {
2091 UserContext ucxt;
2092
2093 if (run_as_table_owner)
2094 SwitchToUntrustedUser(resultRelInfo->ri_RelationDesc->rd_rel->relowner,
2095 &ucxt);
2096 ExecBSTruncateTriggers(estate, resultRelInfo);
2097 if (run_as_table_owner)
2098 RestoreUserContext(&ucxt);
2099 resultRelInfo++;
2100 }
2101
2102 /*
2103 * OK, truncate each table.
2104 */
2105 mySubid = GetCurrentSubTransactionId();
2106
2107 foreach(cell, rels)
2108 {
2109 Relation rel = (Relation) lfirst(cell);
2110
2111 /* Skip partitioned tables as there is nothing to do */
2112 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2113 continue;
2114
2115 /*
2116 * Build the lists of foreign tables belonging to each foreign server
2117 * and pass each list to the foreign data wrapper's callback function,
2118 * so that each server can truncate its all foreign tables in bulk.
2119 * Each list is saved as a single entry in a hash table that uses the
2120 * server OID as lookup key.
2121 */
2122 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2123 {
2125 bool found;
2126 ForeignTruncateInfo *ft_info;
2127
2128 /* First time through, initialize hashtable for foreign tables */
2129 if (!ft_htab)
2130 {
2131 HASHCTL hctl;
2132
2133 memset(&hctl, 0, sizeof(HASHCTL));
2134 hctl.keysize = sizeof(Oid);
2135 hctl.entrysize = sizeof(ForeignTruncateInfo);
2137
2138 ft_htab = hash_create("TRUNCATE for Foreign Tables",
2139 32, /* start small and extend */
2140 &hctl,
2142 }
2143
2144 /* Find or create cached entry for the foreign table */
2145 ft_info = hash_search(ft_htab, &serverid, HASH_ENTER, &found);
2146 if (!found)
2147 ft_info->rels = NIL;
2148
2149 /*
2150 * Save the foreign table in the entry of the server that the
2151 * foreign table belongs to.
2152 */
2153 ft_info->rels = lappend(ft_info->rels, rel);
2154 continue;
2155 }
2156
2157 /*
2158 * Normally, we need a transaction-safe truncation here. However, if
2159 * the table was either created in the current (sub)transaction or has
2160 * a new relfilenumber in the current (sub)transaction, then we can
2161 * just truncate it in-place, because a rollback would cause the whole
2162 * table or the current physical file to be thrown away anyway.
2163 */
2164 if (rel->rd_createSubid == mySubid ||
2165 rel->rd_newRelfilelocatorSubid == mySubid)
2166 {
2167 /* Immediate, non-rollbackable truncation is OK */
2169 }
2170 else
2171 {
2172 Oid heap_relid;
2173 Oid toast_relid;
2174 ReindexParams reindex_params = {0};
2175
2176 /*
2177 * This effectively deletes all rows in the table, and may be done
2178 * in a serializable transaction. In that case we must record a
2179 * rw-conflict in to this transaction from each transaction
2180 * holding a predicate lock on the table.
2181 */
2183
2184 /*
2185 * Need the full transaction-safe pushups.
2186 *
2187 * Create a new empty storage file for the relation, and assign it
2188 * as the relfilenumber value. The old storage file is scheduled
2189 * for deletion at commit.
2190 */
2191 RelationSetNewRelfilenumber(rel, rel->rd_rel->relpersistence);
2192
2193 heap_relid = RelationGetRelid(rel);
2194
2195 /*
2196 * The same for the toast table, if any.
2197 */
2198 toast_relid = rel->rd_rel->reltoastrelid;
2199 if (OidIsValid(toast_relid))
2200 {
2201 Relation toastrel = relation_open(toast_relid,
2203
2205 toastrel->rd_rel->relpersistence);
2206 table_close(toastrel, NoLock);
2207 }
2208
2209 /*
2210 * Reconstruct the indexes to match, and we're done.
2211 */
2213 &reindex_params);
2214 }
2215
2217 }
2218
2219 /* Now go through the hash table, and truncate foreign tables */
2220 if (ft_htab)
2221 {
2222 ForeignTruncateInfo *ft_info;
2223 HASH_SEQ_STATUS seq;
2224
2225 hash_seq_init(&seq, ft_htab);
2226
2227 PG_TRY();
2228 {
2229 while ((ft_info = hash_seq_search(&seq)) != NULL)
2230 {
2231 FdwRoutine *routine = GetFdwRoutineByServerId(ft_info->serverid);
2232
2233 /* truncate_check_rel() has checked that already */
2234 Assert(routine->ExecForeignTruncate != NULL);
2235
2236 routine->ExecForeignTruncate(ft_info->rels,
2237 behavior,
2238 restart_seqs);
2239 }
2240 }
2241 PG_FINALLY();
2242 {
2243 hash_destroy(ft_htab);
2244 }
2245 PG_END_TRY();
2246 }
2247
2248 /*
2249 * Restart owned sequences if we were asked to.
2250 */
2251 foreach(cell, seq_relids)
2252 {
2253 Oid seq_relid = lfirst_oid(cell);
2254
2255 ResetSequence(seq_relid);
2256 }
2257
2258 /*
2259 * Write a WAL record to allow this set of actions to be logically
2260 * decoded.
2261 *
2262 * Assemble an array of relids so we can write a single WAL record for the
2263 * whole action.
2264 */
2265 if (relids_logged != NIL)
2266 {
2267 xl_heap_truncate xlrec;
2268 int i = 0;
2269
2270 /* should only get here if wal_level >= logical */
2272
2273 logrelids = palloc(list_length(relids_logged) * sizeof(Oid));
2274 foreach(cell, relids_logged)
2275 logrelids[i++] = lfirst_oid(cell);
2276
2277 xlrec.dbId = MyDatabaseId;
2278 xlrec.nrelids = list_length(relids_logged);
2279 xlrec.flags = 0;
2280 if (behavior == DROP_CASCADE)
2281 xlrec.flags |= XLH_TRUNCATE_CASCADE;
2282 if (restart_seqs)
2284
2286 XLogRegisterData((char *) &xlrec, SizeOfHeapTruncate);
2287 XLogRegisterData((char *) logrelids, list_length(relids_logged) * sizeof(Oid));
2288
2290
2291 (void) XLogInsert(RM_HEAP_ID, XLOG_HEAP_TRUNCATE);
2292 }
2293
2294 /*
2295 * Process all AFTER STATEMENT TRUNCATE triggers.
2296 */
2297 resultRelInfo = resultRelInfos;
2298 foreach(cell, rels)
2299 {
2300 UserContext ucxt;
2301
2302 if (run_as_table_owner)
2303 SwitchToUntrustedUser(resultRelInfo->ri_RelationDesc->rd_rel->relowner,
2304 &ucxt);
2305 ExecASTruncateTriggers(estate, resultRelInfo);
2306 if (run_as_table_owner)
2307 RestoreUserContext(&ucxt);
2308 resultRelInfo++;
2309 }
2310
2311 /* Handle queued AFTER triggers */
2312 AfterTriggerEndQuery(estate);
2313
2314 /* We can clean up the EState now */
2315 FreeExecutorState(estate);
2316
2317 /*
2318 * Close any rels opened by CASCADE (can't do this while EState still
2319 * holds refs)
2320 */
2321 rels = list_difference_ptr(rels, explicit_rels);
2322 foreach(cell, rels)
2323 {
2324 Relation rel = (Relation) lfirst(cell);
2325
2326 table_close(rel, NoLock);
2327 }
2328}
2329
2330/*
2331 * Check that a given relation is safe to truncate. Subroutine for
2332 * ExecuteTruncate() and RangeVarCallbackForTruncate().
2333 */
2334static void
2336{
2337 char *relname = NameStr(reltuple->relname);
2338
2339 /*
2340 * Only allow truncate on regular tables, foreign tables using foreign
2341 * data wrappers supporting TRUNCATE and partitioned tables (although, the
2342 * latter are only being included here for the following checks; no
2343 * physical truncation will occur in their case.).
2344 */
2345 if (reltuple->relkind == RELKIND_FOREIGN_TABLE)
2346 {
2347 Oid serverid = GetForeignServerIdByRelId(relid);
2348 FdwRoutine *fdwroutine = GetFdwRoutineByServerId(serverid);
2349
2350 if (!fdwroutine->ExecForeignTruncate)
2351 ereport(ERROR,
2352 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2353 errmsg("cannot truncate foreign table \"%s\"",
2354 relname)));
2355 }
2356 else if (reltuple->relkind != RELKIND_RELATION &&
2357 reltuple->relkind != RELKIND_PARTITIONED_TABLE)
2358 ereport(ERROR,
2359 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2360 errmsg("\"%s\" is not a table", relname)));
2361
2362 /*
2363 * Most system catalogs can't be truncated at all, or at least not unless
2364 * allow_system_table_mods=on. As an exception, however, we allow
2365 * pg_largeobject to be truncated as part of pg_upgrade, because we need
2366 * to change its relfilenode to match the old cluster, and allowing a
2367 * TRUNCATE command to be executed is the easiest way of doing that.
2368 */
2369 if (!allowSystemTableMods && IsSystemClass(relid, reltuple)
2370 && (!IsBinaryUpgrade || relid != LargeObjectRelationId))
2371 ereport(ERROR,
2372 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2373 errmsg("permission denied: \"%s\" is a system catalog",
2374 relname)));
2375
2377}
2378
2379/*
2380 * Check that current user has the permission to truncate given relation.
2381 */
2382static void
2384{
2385 char *relname = NameStr(reltuple->relname);
2386 AclResult aclresult;
2387
2388 /* Permissions checks */
2389 aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_TRUNCATE);
2390 if (aclresult != ACLCHECK_OK)
2391 aclcheck_error(aclresult, get_relkind_objtype(reltuple->relkind),
2392 relname);
2393}
2394
2395/*
2396 * Set of extra sanity checks to check if a given relation is safe to
2397 * truncate. This is split with truncate_check_rel() as
2398 * RangeVarCallbackForTruncate() cannot open a Relation yet.
2399 */
2400static void
2402{
2403 /*
2404 * Don't allow truncate on temp tables of other backends ... their local
2405 * buffer manager is not going to cope.
2406 */
2407 if (RELATION_IS_OTHER_TEMP(rel))
2408 ereport(ERROR,
2409 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2410 errmsg("cannot truncate temporary tables of other sessions")));
2411
2412 /*
2413 * Also check for active uses of the relation in the current transaction,
2414 * including open scans and pending AFTER trigger events.
2415 */
2416 CheckTableNotInUse(rel, "TRUNCATE");
2417}
2418
2419/*
2420 * storage_name
2421 * returns the name corresponding to a typstorage/attstorage enum value
2422 */
2423static const char *
2425{
2426 switch (c)
2427 {
2428 case TYPSTORAGE_PLAIN:
2429 return "PLAIN";
2430 case TYPSTORAGE_EXTERNAL:
2431 return "EXTERNAL";
2432 case TYPSTORAGE_EXTENDED:
2433 return "EXTENDED";
2434 case TYPSTORAGE_MAIN:
2435 return "MAIN";
2436 default:
2437 return "???";
2438 }
2439}
2440
2441/*----------
2442 * MergeAttributes
2443 * Returns new schema given initial schema and superclasses.
2444 *
2445 * Input arguments:
2446 * 'columns' is the column/attribute definition for the table. (It's a list
2447 * of ColumnDef's.) It is destructively changed.
2448 * 'supers' is a list of OIDs of parent relations, already locked by caller.
2449 * 'relpersistence' is the persistence type of the table.
2450 * 'is_partition' tells if the table is a partition.
2451 *
2452 * Output arguments:
2453 * 'supconstr' receives a list of CookedConstraint representing
2454 * CHECK constraints belonging to parent relations, updated as
2455 * necessary to be valid for the child.
2456 * 'supnotnulls' receives a list of CookedConstraint representing
2457 * not-null constraints based on those from parent relations.
2458 *
2459 * Return value:
2460 * Completed schema list.
2461 *
2462 * Notes:
2463 * The order in which the attributes are inherited is very important.
2464 * Intuitively, the inherited attributes should come first. If a table
2465 * inherits from multiple parents, the order of those attributes are
2466 * according to the order of the parents specified in CREATE TABLE.
2467 *
2468 * Here's an example:
2469 *
2470 * create table person (name text, age int4, location point);
2471 * create table emp (salary int4, manager text) inherits(person);
2472 * create table student (gpa float8) inherits (person);
2473 * create table stud_emp (percent int4) inherits (emp, student);
2474 *
2475 * The order of the attributes of stud_emp is:
2476 *
2477 * person {1:name, 2:age, 3:location}
2478 * / \
2479 * {6:gpa} student emp {4:salary, 5:manager}
2480 * \ /
2481 * stud_emp {7:percent}
2482 *
2483 * If the same attribute name appears multiple times, then it appears
2484 * in the result table in the proper location for its first appearance.
2485 *
2486 * Constraints (including not-null constraints) for the child table
2487 * are the union of all relevant constraints, from both the child schema
2488 * and parent tables. In addition, in legacy inheritance, each column that
2489 * appears in a primary key in any of the parents also gets a NOT NULL
2490 * constraint (partitioning doesn't need this, because the PK itself gets
2491 * inherited.)
2492 *
2493 * The default value for a child column is defined as:
2494 * (1) If the child schema specifies a default, that value is used.
2495 * (2) If neither the child nor any parent specifies a default, then
2496 * the column will not have a default.
2497 * (3) If conflicting defaults are inherited from different parents
2498 * (and not overridden by the child), an error is raised.
2499 * (4) Otherwise the inherited default is used.
2500 *
2501 * Note that the default-value infrastructure is used for generated
2502 * columns' expressions too, so most of the preceding paragraph applies
2503 * to generation expressions too. We insist that a child column be
2504 * generated if and only if its parent(s) are, but it need not have
2505 * the same generation expression.
2506 *----------
2507 */
2508static List *
2509MergeAttributes(List *columns, const List *supers, char relpersistence,
2510 bool is_partition, List **supconstr, List **supnotnulls)
2511{
2512 List *inh_columns = NIL;
2513 List *constraints = NIL;
2514 List *nnconstraints = NIL;
2515 bool have_bogus_defaults = false;
2516 int child_attno;
2517 static Node bogus_marker = {0}; /* marks conflicting defaults */
2518 List *saved_columns = NIL;
2519 ListCell *lc;
2520
2521 /*
2522 * Check for and reject tables with too many columns. We perform this
2523 * check relatively early for two reasons: (a) we don't run the risk of
2524 * overflowing an AttrNumber in subsequent code (b) an O(n^2) algorithm is
2525 * okay if we're processing <= 1600 columns, but could take minutes to
2526 * execute if the user attempts to create a table with hundreds of
2527 * thousands of columns.
2528 *
2529 * Note that we also need to check that we do not exceed this figure after
2530 * including columns from inherited relations.
2531 */
2532 if (list_length(columns) > MaxHeapAttributeNumber)
2533 ereport(ERROR,
2534 (errcode(ERRCODE_TOO_MANY_COLUMNS),
2535 errmsg("tables can have at most %d columns",
2537
2538 /*
2539 * Check for duplicate names in the explicit list of attributes.
2540 *
2541 * Although we might consider merging such entries in the same way that we
2542 * handle name conflicts for inherited attributes, it seems to make more
2543 * sense to assume such conflicts are errors.
2544 *
2545 * We don't use foreach() here because we have two nested loops over the
2546 * columns list, with possible element deletions in the inner one. If we
2547 * used foreach_delete_current() it could only fix up the state of one of
2548 * the loops, so it seems cleaner to use looping over list indexes for
2549 * both loops. Note that any deletion will happen beyond where the outer
2550 * loop is, so its index never needs adjustment.
2551 */
2552 for (int coldefpos = 0; coldefpos < list_length(columns); coldefpos++)
2553 {
2554 ColumnDef *coldef = list_nth_node(ColumnDef, columns, coldefpos);
2555
2556 if (!is_partition && coldef->typeName == NULL)
2557 {
2558 /*
2559 * Typed table column option that does not belong to a column from
2560 * the type. This works because the columns from the type come
2561 * first in the list. (We omit this check for partition column
2562 * lists; those are processed separately below.)
2563 */
2564 ereport(ERROR,
2565 (errcode(ERRCODE_UNDEFINED_COLUMN),
2566 errmsg("column \"%s\" does not exist",
2567 coldef->colname)));
2568 }
2569
2570 /* restpos scans all entries beyond coldef; incr is in loop body */
2571 for (int restpos = coldefpos + 1; restpos < list_length(columns);)
2572 {
2573 ColumnDef *restdef = list_nth_node(ColumnDef, columns, restpos);
2574
2575 if (strcmp(coldef->colname, restdef->colname) == 0)
2576 {
2577 if (coldef->is_from_type)
2578 {
2579 /*
2580 * merge the column options into the column from the type
2581 */
2582 coldef->is_not_null = restdef->is_not_null;
2583 coldef->raw_default = restdef->raw_default;
2584 coldef->cooked_default = restdef->cooked_default;
2585 coldef->constraints = restdef->constraints;
2586 coldef->is_from_type = false;
2587 columns = list_delete_nth_cell(columns, restpos);
2588 }
2589 else
2590 ereport(ERROR,
2591 (errcode(ERRCODE_DUPLICATE_COLUMN),
2592 errmsg("column \"%s\" specified more than once",
2593 coldef->colname)));
2594 }
2595 else
2596 restpos++;
2597 }
2598 }
2599
2600 /*
2601 * In case of a partition, there are no new column definitions, only dummy
2602 * ColumnDefs created for column constraints. Set them aside for now and
2603 * process them at the end.
2604 */
2605 if (is_partition)
2606 {
2607 saved_columns = columns;
2608 columns = NIL;
2609 }
2610
2611 /*
2612 * Scan the parents left-to-right, and merge their attributes to form a
2613 * list of inherited columns (inh_columns).
2614 */
2615 child_attno = 0;
2616 foreach(lc, supers)
2617 {
2618 Oid parent = lfirst_oid(lc);
2619 Relation relation;
2620 TupleDesc tupleDesc;
2621 TupleConstr *constr;
2622 AttrMap *newattmap;
2623 List *inherited_defaults;
2624 List *cols_with_defaults;
2625 List *nnconstrs;
2626 ListCell *lc1;
2627 ListCell *lc2;
2628 Bitmapset *nncols = NULL;
2629
2630 /* caller already got lock */
2631 relation = table_open(parent, NoLock);
2632
2633 /*
2634 * Check for active uses of the parent partitioned table in the
2635 * current transaction, such as being used in some manner by an
2636 * enclosing command.
2637 */
2638 if (is_partition)
2639 CheckTableNotInUse(relation, "CREATE TABLE .. PARTITION OF");
2640
2641 /*
2642 * We do not allow partitioned tables and partitions to participate in
2643 * regular inheritance.
2644 */
2645 if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && !is_partition)
2646 ereport(ERROR,
2647 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2648 errmsg("cannot inherit from partitioned table \"%s\"",
2649 RelationGetRelationName(relation))));
2650 if (relation->rd_rel->relispartition && !is_partition)
2651 ereport(ERROR,
2652 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2653 errmsg("cannot inherit from partition \"%s\"",
2654 RelationGetRelationName(relation))));
2655
2656 if (relation->rd_rel->relkind != RELKIND_RELATION &&
2657 relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
2658 relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
2659 ereport(ERROR,
2660 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2661 errmsg("inherited relation \"%s\" is not a table or foreign table",
2662 RelationGetRelationName(relation))));
2663
2664 /*
2665 * If the parent is permanent, so must be all of its partitions. Note
2666 * that inheritance allows that case.
2667 */
2668 if (is_partition &&
2669 relation->rd_rel->relpersistence != RELPERSISTENCE_TEMP &&
2670 relpersistence == RELPERSISTENCE_TEMP)
2671 ereport(ERROR,
2672 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2673 errmsg("cannot create a temporary relation as partition of permanent relation \"%s\"",
2674 RelationGetRelationName(relation))));
2675
2676 /* Permanent rels cannot inherit from temporary ones */
2677 if (relpersistence != RELPERSISTENCE_TEMP &&
2678 relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
2679 ereport(ERROR,
2680 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2681 errmsg(!is_partition
2682 ? "cannot inherit from temporary relation \"%s\""
2683 : "cannot create a permanent relation as partition of temporary relation \"%s\"",
2684 RelationGetRelationName(relation))));
2685
2686 /* If existing rel is temp, it must belong to this session */
2687 if (relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
2688 !relation->rd_islocaltemp)
2689 ereport(ERROR,
2690 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2691 errmsg(!is_partition
2692 ? "cannot inherit from temporary relation of another session"
2693 : "cannot create as partition of temporary relation of another session")));
2694
2695 /*
2696 * We should have an UNDER permission flag for this, but for now,
2697 * demand that creator of a child table own the parent.
2698 */
2699 if (!object_ownercheck(RelationRelationId, RelationGetRelid(relation), GetUserId()))
2701 RelationGetRelationName(relation));
2702
2703 tupleDesc = RelationGetDescr(relation);
2704 constr = tupleDesc->constr;
2705
2706 /*
2707 * newattmap->attnums[] will contain the child-table attribute numbers
2708 * for the attributes of this parent table. (They are not the same
2709 * for parents after the first one, nor if we have dropped columns.)
2710 */
2711 newattmap = make_attrmap(tupleDesc->natts);
2712
2713 /* We can't process inherited defaults until newattmap is complete. */
2714 inherited_defaults = cols_with_defaults = NIL;
2715
2716 /*
2717 * Request attnotnull on columns that have a not-null constraint
2718 * that's not marked NO INHERIT.
2719 */
2720 nnconstrs = RelationGetNotNullConstraints(RelationGetRelid(relation),
2721 true, false);
2722 foreach_ptr(CookedConstraint, cc, nnconstrs)
2723 nncols = bms_add_member(nncols, cc->attnum);
2724
2725 for (AttrNumber parent_attno = 1; parent_attno <= tupleDesc->natts;
2726 parent_attno++)
2727 {
2728 Form_pg_attribute attribute = TupleDescAttr(tupleDesc,
2729 parent_attno - 1);
2730 char *attributeName = NameStr(attribute->attname);
2731 int exist_attno;
2732 ColumnDef *newdef;
2733 ColumnDef *mergeddef;
2734
2735 /*
2736 * Ignore dropped columns in the parent.
2737 */
2738 if (attribute->attisdropped)
2739 continue; /* leave newattmap->attnums entry as zero */
2740
2741 /*
2742 * Create new column definition
2743 */
2744 newdef = makeColumnDef(attributeName, attribute->atttypid,
2745 attribute->atttypmod, attribute->attcollation);
2746 newdef->storage = attribute->attstorage;
2747 newdef->generated = attribute->attgenerated;
2748 if (CompressionMethodIsValid(attribute->attcompression))
2749 newdef->compression =
2750 pstrdup(GetCompressionMethodName(attribute->attcompression));
2751
2752 /*
2753 * Regular inheritance children are independent enough not to
2754 * inherit identity columns. But partitions are integral part of
2755 * a partitioned table and inherit identity column.
2756 */
2757 if (is_partition)
2758 newdef->identity = attribute->attidentity;
2759
2760 /*
2761 * Does it match some previously considered column from another
2762 * parent?
2763 */
2764 exist_attno = findAttrByName(attributeName, inh_columns);
2765 if (exist_attno > 0)
2766 {
2767 /*
2768 * Yes, try to merge the two column definitions.
2769 */
2770 mergeddef = MergeInheritedAttribute(inh_columns, exist_attno, newdef);
2771
2772 newattmap->attnums[parent_attno - 1] = exist_attno;
2773
2774 /*
2775 * Partitions have only one parent, so conflict should never
2776 * occur.
2777 */
2778 Assert(!is_partition);
2779 }
2780 else
2781 {
2782 /*
2783 * No, create a new inherited column
2784 */
2785 newdef->inhcount = 1;
2786 newdef->is_local = false;
2787 inh_columns = lappend(inh_columns, newdef);
2788
2789 newattmap->attnums[parent_attno - 1] = ++child_attno;
2790 mergeddef = newdef;
2791 }
2792
2793 /*
2794 * mark attnotnull if parent has it
2795 */
2796 if (bms_is_member(parent_attno, nncols))
2797 mergeddef->is_not_null = true;
2798
2799 /*
2800 * Locate default/generation expression if any
2801 */
2802 if (attribute->atthasdef)
2803 {
2804 Node *this_default;
2805
2806 this_default = TupleDescGetDefault(tupleDesc, parent_attno);
2807 if (this_default == NULL)
2808 elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",
2809 parent_attno, RelationGetRelationName(relation));
2810
2811 /*
2812 * If it's a GENERATED default, it might contain Vars that
2813 * need to be mapped to the inherited column(s)' new numbers.
2814 * We can't do that till newattmap is ready, so just remember
2815 * all the inherited default expressions for the moment.
2816 */
2817 inherited_defaults = lappend(inherited_defaults, this_default);
2818 cols_with_defaults = lappend(cols_with_defaults, mergeddef);
2819 }
2820 }
2821
2822 /*
2823 * Now process any inherited default expressions, adjusting attnos
2824 * using the completed newattmap map.
2825 */
2826 forboth(lc1, inherited_defaults, lc2, cols_with_defaults)
2827 {
2828 Node *this_default = (Node *) lfirst(lc1);
2829 ColumnDef *def = (ColumnDef *) lfirst(lc2);
2830 bool found_whole_row;
2831
2832 /* Adjust Vars to match new table's column numbering */
2833 this_default = map_variable_attnos(this_default,
2834 1, 0,
2835 newattmap,
2836 InvalidOid, &found_whole_row);
2837
2838 /*
2839 * For the moment we have to reject whole-row variables. We could
2840 * convert them, if we knew the new table's rowtype OID, but that
2841 * hasn't been assigned yet. (A variable could only appear in a
2842 * generation expression, so the error message is correct.)
2843 */
2844 if (found_whole_row)
2845 ereport(ERROR,
2846 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2847 errmsg("cannot convert whole-row table reference"),
2848 errdetail("Generation expression for column \"%s\" contains a whole-row reference to table \"%s\".",
2849 def->colname,
2850 RelationGetRelationName(relation))));
2851
2852 /*
2853 * If we already had a default from some prior parent, check to
2854 * see if they are the same. If so, no problem; if not, mark the
2855 * column as having a bogus default. Below, we will complain if
2856 * the bogus default isn't overridden by the child columns.
2857 */
2858 Assert(def->raw_default == NULL);
2859 if (def->cooked_default == NULL)
2860 def->cooked_default = this_default;
2861 else if (!equal(def->cooked_default, this_default))
2862 {
2863 def->cooked_default = &bogus_marker;
2864 have_bogus_defaults = true;
2865 }
2866 }
2867
2868 /*
2869 * Now copy the CHECK constraints of this parent, adjusting attnos
2870 * using the completed newattmap map. Identically named constraints
2871 * are merged if possible, else we throw error.
2872 */
2873 if (constr && constr->num_check > 0)
2874 {
2875 ConstrCheck *check = constr->check;
2876
2877 for (int i = 0; i < constr->num_check; i++)
2878 {
2879 char *name = check[i].ccname;
2880 Node *expr;
2881 bool found_whole_row;
2882
2883 /* ignore if the constraint is non-inheritable */
2884 if (check[i].ccnoinherit)
2885 continue;
2886
2887 /* Adjust Vars to match new table's column numbering */
2888 expr = map_variable_attnos(stringToNode(check[i].ccbin),
2889 1, 0,
2890 newattmap,
2891 InvalidOid, &found_whole_row);
2892
2893 /*
2894 * For the moment we have to reject whole-row variables. We
2895 * could convert them, if we knew the new table's rowtype OID,
2896 * but that hasn't been assigned yet.
2897 */
2898 if (found_whole_row)
2899 ereport(ERROR,
2900 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2901 errmsg("cannot convert whole-row table reference"),
2902 errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
2903 name,
2904 RelationGetRelationName(relation))));
2905
2906 constraints = MergeCheckConstraint(constraints, name, expr,
2907 check[i].ccenforced);
2908 }
2909 }
2910
2911 /*
2912 * Also copy the not-null constraints from this parent. The
2913 * attnotnull markings were already installed above.
2914 */
2915 foreach_ptr(CookedConstraint, nn, nnconstrs)
2916 {
2917 Assert(nn->contype == CONSTR_NOTNULL);
2918
2919 nn->attnum = newattmap->attnums[nn->attnum - 1];
2920
2921 nnconstraints = lappend(nnconstraints, nn);
2922 }
2923
2924 free_attrmap(newattmap);
2925
2926 /*
2927 * Close the parent rel, but keep our lock on it until xact commit.
2928 * That will prevent someone else from deleting or ALTERing the parent
2929 * before the child is committed.
2930 */
2931 table_close(relation, NoLock);
2932 }
2933
2934 /*
2935 * If we had no inherited attributes, the result columns are just the
2936 * explicitly declared columns. Otherwise, we need to merge the declared
2937 * columns into the inherited column list. Although, we never have any
2938 * explicitly declared columns if the table is a partition.
2939 */
2940 if (inh_columns != NIL)
2941 {
2942 int newcol_attno = 0;
2943
2944 foreach(lc, columns)
2945 {
2946 ColumnDef *newdef = lfirst_node(ColumnDef, lc);
2947 char *attributeName = newdef->colname;
2948 int exist_attno;
2949
2950 /*
2951 * Partitions have only one parent and have no column definitions
2952 * of their own, so conflict should never occur.
2953 */
2954 Assert(!is_partition);
2955
2956 newcol_attno++;
2957
2958 /*
2959 * Does it match some inherited column?
2960 */
2961 exist_attno = findAttrByName(attributeName, inh_columns);
2962 if (exist_attno > 0)
2963 {
2964 /*
2965 * Yes, try to merge the two column definitions.
2966 */
2967 MergeChildAttribute(inh_columns, exist_attno, newcol_attno, newdef);
2968 }
2969 else
2970 {
2971 /*
2972 * No, attach new column unchanged to result columns.
2973 */
2974 inh_columns = lappend(inh_columns, newdef);
2975 }
2976 }
2977
2978 columns = inh_columns;
2979
2980 /*
2981 * Check that we haven't exceeded the legal # of columns after merging
2982 * in inherited columns.
2983 */
2984 if (list_length(columns) > MaxHeapAttributeNumber)
2985 ereport(ERROR,
2986 (errcode(ERRCODE_TOO_MANY_COLUMNS),
2987 errmsg("tables can have at most %d columns",
2989 }
2990
2991 /*
2992 * Now that we have the column definition list for a partition, we can
2993 * check whether the columns referenced in the column constraint specs
2994 * actually exist. Also, merge column defaults.
2995 */
2996 if (is_partition)
2997 {
2998 foreach(lc, saved_columns)
2999 {
3000 ColumnDef *restdef = lfirst(lc);
3001 bool found = false;
3002 ListCell *l;
3003
3004 foreach(l, columns)
3005 {
3006 ColumnDef *coldef = lfirst(l);
3007
3008 if (strcmp(coldef->colname, restdef->colname) == 0)
3009 {
3010 found = true;
3011
3012 /*
3013 * Check for conflicts related to generated columns.
3014 *
3015 * Same rules as above: generated-ness has to match the
3016 * parent, but the contents of the generation expression
3017 * can be different.
3018 */
3019 if (coldef->generated)
3020 {
3021 if (restdef->raw_default && !restdef->generated)
3022 ereport(ERROR,
3023 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3024 errmsg("column \"%s\" inherits from generated column but specifies default",
3025 restdef->colname)));
3026 if (restdef->identity)
3027 ereport(ERROR,
3028 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3029 errmsg("column \"%s\" inherits from generated column but specifies identity",
3030 restdef->colname)));
3031 }
3032 else
3033 {
3034 if (restdef->generated)
3035 ereport(ERROR,
3036 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3037 errmsg("child column \"%s\" specifies generation expression",
3038 restdef->colname),
3039 errhint("A child table column cannot be generated unless its parent column is.")));
3040 }
3041
3042 /*
3043 * Override the parent's default value for this column
3044 * (coldef->cooked_default) with the partition's local
3045 * definition (restdef->raw_default), if there's one. It
3046 * should be physically impossible to get a cooked default
3047 * in the local definition or a raw default in the
3048 * inherited definition, but make sure they're nulls, for
3049 * future-proofing.
3050 */
3051 Assert(restdef->cooked_default == NULL);
3052 Assert(coldef->raw_default == NULL);
3053 if (restdef->raw_default)
3054 {
3055 coldef->raw_default = restdef->raw_default;
3056 coldef->cooked_default = NULL;
3057 }
3058 }
3059 }
3060
3061 /* complain for constraints on columns not in parent */
3062 if (!found)
3063 ereport(ERROR,
3064 (errcode(ERRCODE_UNDEFINED_COLUMN),
3065 errmsg("column \"%s\" does not exist",
3066 restdef->colname)));
3067 }
3068 }
3069
3070 /*
3071 * If we found any conflicting parent default values, check to make sure
3072 * they were overridden by the child.
3073 */
3074 if (have_bogus_defaults)
3075 {
3076 foreach(lc, columns)
3077 {
3078 ColumnDef *def = lfirst(lc);
3079
3080 if (def->cooked_default == &bogus_marker)
3081 {
3082 if (def->generated)
3083 ereport(ERROR,
3084 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3085 errmsg("column \"%s\" inherits conflicting generation expressions",
3086 def->colname),
3087 errhint("To resolve the conflict, specify a generation expression explicitly.")));
3088 else
3089 ereport(ERROR,
3090 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3091 errmsg("column \"%s\" inherits conflicting default values",
3092 def->colname),
3093 errhint("To resolve the conflict, specify a default explicitly.")));
3094 }
3095 }
3096 }
3097
3098 *supconstr = constraints;
3099 *supnotnulls = nnconstraints;
3100
3101 return columns;
3102}
3103
3104
3105/*
3106 * MergeCheckConstraint
3107 * Try to merge an inherited CHECK constraint with previous ones
3108 *
3109 * If we inherit identically-named constraints from multiple parents, we must
3110 * merge them, or throw an error if they don't have identical definitions.
3111 *
3112 * constraints is a list of CookedConstraint structs for previous constraints.
3113 *
3114 * If the new constraint matches an existing one, then the existing
3115 * constraint's inheritance count is updated. If there is a conflict (same
3116 * name but different expression), throw an error. If the constraint neither
3117 * matches nor conflicts with an existing one, a new constraint is appended to
3118 * the list.
3119 */
3120static List *
3121MergeCheckConstraint(List *constraints, const char *name, Node *expr, bool is_enforced)
3122{
3123 ListCell *lc;
3124 CookedConstraint *newcon;
3125
3126 foreach(lc, constraints)
3127 {
3129
3130 Assert(ccon->contype == CONSTR_CHECK);
3131
3132 /* Non-matching names never conflict */
3133 if (strcmp(ccon->name, name) != 0)
3134 continue;
3135
3136 if (equal(expr, ccon->expr))
3137 {
3138 /* OK to merge constraint with existing */
3139 if (pg_add_s16_overflow(ccon->inhcount, 1,
3140 &ccon->inhcount))
3141 ereport(ERROR,
3142 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3143 errmsg("too many inheritance parents"));
3144
3145 /*
3146 * When enforceability differs, the merged constraint should be
3147 * marked as ENFORCED because one of the parents is ENFORCED.
3148 */
3149 if (!ccon->is_enforced && is_enforced)
3150 {
3151 ccon->is_enforced = true;
3152 ccon->skip_validation = false;
3153 }
3154
3155 return constraints;
3156 }
3157
3158 ereport(ERROR,
3160 errmsg("check constraint name \"%s\" appears multiple times but with different expressions",
3161 name)));
3162 }
3163
3164 /*
3165 * Constraint couldn't be merged with an existing one and also didn't
3166 * conflict with an existing one, so add it as a new one to the list.
3167 */
3169 newcon->contype = CONSTR_CHECK;
3170 newcon->name = pstrdup(name);
3171 newcon->expr = expr;
3172 newcon->inhcount = 1;
3173 newcon->is_enforced = is_enforced;
3174 newcon->skip_validation = !is_enforced;
3175 return lappend(constraints, newcon);
3176}
3177
3178/*
3179 * MergeChildAttribute
3180 * Merge given child attribute definition into given inherited attribute.
3181 *
3182 * Input arguments:
3183 * 'inh_columns' is the list of inherited ColumnDefs.
3184 * 'exist_attno' is the number of the inherited attribute in inh_columns
3185 * 'newcol_attno' is the attribute number in child table's schema definition
3186 * 'newdef' is the column/attribute definition from the child table.
3187 *
3188 * The ColumnDef in 'inh_columns' list is modified. The child attribute's
3189 * ColumnDef remains unchanged.
3190 *
3191 * Notes:
3192 * - The attribute is merged according to the rules laid out in the prologue
3193 * of MergeAttributes().
3194 * - If matching inherited attribute exists but the child attribute can not be
3195 * merged into it, the function throws respective errors.
3196 * - A partition can not have its own column definitions. Hence this function
3197 * is applicable only to a regular inheritance child.
3198 */
3199static void
3200MergeChildAttribute(List *inh_columns, int exist_attno, int newcol_attno, const ColumnDef *newdef)
3201{
3202 char *attributeName = newdef->colname;
3203 ColumnDef *inhdef;
3204 Oid inhtypeid,
3205 newtypeid;
3206 int32 inhtypmod,
3207 newtypmod;
3208 Oid inhcollid,
3209 newcollid;
3210
3211 if (exist_attno == newcol_attno)
3213 (errmsg("merging column \"%s\" with inherited definition",
3214 attributeName)));
3215 else
3217 (errmsg("moving and merging column \"%s\" with inherited definition", attributeName),
3218 errdetail("User-specified column moved to the position of the inherited column.")));
3219
3220 inhdef = list_nth_node(ColumnDef, inh_columns, exist_attno - 1);
3221
3222 /*
3223 * Must have the same type and typmod
3224 */
3225 typenameTypeIdAndMod(NULL, inhdef->typeName, &inhtypeid, &inhtypmod);
3226 typenameTypeIdAndMod(NULL, newdef->typeName, &newtypeid, &newtypmod);
3227 if (inhtypeid != newtypeid || inhtypmod != newtypmod)
3228 ereport(ERROR,
3229 (errcode(ERRCODE_DATATYPE_MISMATCH),
3230 errmsg("column \"%s\" has a type conflict",
3231 attributeName),
3232 errdetail("%s versus %s",
3233 format_type_with_typemod(inhtypeid, inhtypmod),
3234 format_type_with_typemod(newtypeid, newtypmod))));
3235
3236 /*
3237 * Must have the same collation
3238 */
3239 inhcollid = GetColumnDefCollation(NULL, inhdef, inhtypeid);
3240 newcollid = GetColumnDefCollation(NULL, newdef, newtypeid);
3241 if (inhcollid != newcollid)
3242 ereport(ERROR,
3243 (errcode(ERRCODE_COLLATION_MISMATCH),
3244 errmsg("column \"%s\" has a collation conflict",
3245 attributeName),
3246 errdetail("\"%s\" versus \"%s\"",
3247 get_collation_name(inhcollid),
3248 get_collation_name(newcollid))));
3249
3250 /*
3251 * Identity is never inherited by a regular inheritance child. Pick
3252 * child's identity definition if there's one.
3253 */
3254 inhdef->identity = newdef->identity;
3255
3256 /*
3257 * Copy storage parameter
3258 */
3259 if (inhdef->storage == 0)
3260 inhdef->storage = newdef->storage;
3261 else if (newdef->storage != 0 && inhdef->storage != newdef->storage)
3262 ereport(ERROR,
3263 (errcode(ERRCODE_DATATYPE_MISMATCH),
3264 errmsg("column \"%s\" has a storage parameter conflict",
3265 attributeName),
3266 errdetail("%s versus %s",
3267 storage_name(inhdef->storage),
3268 storage_name(newdef->storage))));
3269
3270 /*
3271 * Copy compression parameter
3272 */
3273 if (inhdef->compression == NULL)
3274 inhdef->compression = newdef->compression;
3275 else if (newdef->compression != NULL)
3276 {
3277 if (strcmp(inhdef->compression, newdef->compression) != 0)
3278 ereport(ERROR,
3279 (errcode(ERRCODE_DATATYPE_MISMATCH),
3280 errmsg("column \"%s\" has a compression method conflict",
3281 attributeName),
3282 errdetail("%s versus %s", inhdef->compression, newdef->compression)));
3283 }
3284
3285 /*
3286 * Merge of not-null constraints = OR 'em together
3287 */
3288 inhdef->is_not_null |= newdef->is_not_null;
3289
3290 /*
3291 * Check for conflicts related to generated columns.
3292 *
3293 * If the parent column is generated, the child column will be made a
3294 * generated column if it isn't already. If it is a generated column,
3295 * we'll take its generation expression in preference to the parent's. We
3296 * must check that the child column doesn't specify a default value or
3297 * identity, which matches the rules for a single column in
3298 * parse_utilcmd.c.
3299 *
3300 * Conversely, if the parent column is not generated, the child column
3301 * can't be either. (We used to allow that, but it results in being able
3302 * to override the generation expression via UPDATEs through the parent.)
3303 */
3304 if (inhdef->generated)
3305 {
3306 if (newdef->raw_default && !newdef->generated)
3307 ereport(ERROR,
3308 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3309 errmsg("column \"%s\" inherits from generated column but specifies default",
3310 inhdef->colname)));
3311 if (newdef->identity)
3312 ereport(ERROR,
3313 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3314 errmsg("column \"%s\" inherits from generated column but specifies identity",
3315 inhdef->colname)));
3316 }
3317 else
3318 {
3319 if (newdef->generated)
3320 ereport(ERROR,
3321 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3322 errmsg("child column \"%s\" specifies generation expression",
3323 inhdef->colname),
3324 errhint("A child table column cannot be generated unless its parent column is.")));
3325 }
3326
3327 /*
3328 * If new def has a default, override previous default
3329 */
3330 if (newdef->raw_default != NULL)
3331 {
3332 inhdef->raw_default = newdef->raw_default;
3333 inhdef->cooked_default = newdef->cooked_default;
3334 }
3335
3336 /* Mark the column as locally defined */
3337 inhdef->is_local = true;
3338}
3339
3340/*
3341 * MergeInheritedAttribute
3342 * Merge given parent attribute definition into specified attribute
3343 * inherited from the previous parents.
3344 *
3345 * Input arguments:
3346 * 'inh_columns' is the list of previously inherited ColumnDefs.
3347 * 'exist_attno' is the number the existing matching attribute in inh_columns.
3348 * 'newdef' is the new parent column/attribute definition to be merged.
3349 *
3350 * The matching ColumnDef in 'inh_columns' list is modified and returned.
3351 *
3352 * Notes:
3353 * - The attribute is merged according to the rules laid out in the prologue
3354 * of MergeAttributes().
3355 * - If matching inherited attribute exists but the new attribute can not be
3356 * merged into it, the function throws respective errors.
3357 * - A partition inherits from only a single parent. Hence this function is
3358 * applicable only to a regular inheritance.
3359 */
3360static ColumnDef *
3362 int exist_attno,
3363 const ColumnDef *newdef)
3364{
3365 char *attributeName = newdef->colname;
3366 ColumnDef *prevdef;
3367 Oid prevtypeid,
3368 newtypeid;
3369 int32 prevtypmod,
3370 newtypmod;
3371 Oid prevcollid,
3372 newcollid;
3373
3375 (errmsg("merging multiple inherited definitions of column \"%s\"",
3376 attributeName)));
3377 prevdef = list_nth_node(ColumnDef, inh_columns, exist_attno - 1);
3378
3379 /*
3380 * Must have the same type and typmod
3381 */
3382 typenameTypeIdAndMod(NULL, prevdef->typeName, &prevtypeid, &prevtypmod);
3383 typenameTypeIdAndMod(NULL, newdef->typeName, &newtypeid, &newtypmod);
3384 if (prevtypeid != newtypeid || prevtypmod != newtypmod)
3385 ereport(ERROR,
3386 (errcode(ERRCODE_DATATYPE_MISMATCH),
3387 errmsg("inherited column \"%s\" has a type conflict",
3388 attributeName),
3389 errdetail("%s versus %s",
3390 format_type_with_typemod(prevtypeid, prevtypmod),
3391 format_type_with_typemod(newtypeid, newtypmod))));
3392
3393 /*
3394 * Must have the same collation
3395 */
3396 prevcollid = GetColumnDefCollation(NULL, prevdef, prevtypeid);
3397 newcollid = GetColumnDefCollation(NULL, newdef, newtypeid);
3398 if (prevcollid != newcollid)
3399 ereport(ERROR,
3400 (errcode(ERRCODE_COLLATION_MISMATCH),
3401 errmsg("inherited column \"%s\" has a collation conflict",
3402 attributeName),
3403 errdetail("\"%s\" versus \"%s\"",
3404 get_collation_name(prevcollid),
3405 get_collation_name(newcollid))));
3406
3407 /*
3408 * Copy/check storage parameter
3409 */
3410 if (prevdef->storage == 0)
3411 prevdef->storage = newdef->storage;
3412 else if (prevdef->storage != newdef->storage)
3413 ereport(ERROR,
3414 (errcode(ERRCODE_DATATYPE_MISMATCH),
3415 errmsg("inherited column \"%s\" has a storage parameter conflict",
3416 attributeName),
3417 errdetail("%s versus %s",
3418 storage_name(prevdef->storage),
3419 storage_name(newdef->storage))));
3420
3421 /*
3422 * Copy/check compression parameter
3423 */
3424 if (prevdef->compression == NULL)
3425 prevdef->compression = newdef->compression;
3426 else if (newdef->compression != NULL)
3427 {
3428 if (strcmp(prevdef->compression, newdef->compression) != 0)
3429 ereport(ERROR,
3430 (errcode(ERRCODE_DATATYPE_MISMATCH),
3431 errmsg("column \"%s\" has a compression method conflict",
3432 attributeName),
3433 errdetail("%s versus %s",
3434 prevdef->compression, newdef->compression)));
3435 }
3436
3437 /*
3438 * Check for GENERATED conflicts
3439 */
3440 if (prevdef->generated != newdef->generated)
3441 ereport(ERROR,
3442 (errcode(ERRCODE_DATATYPE_MISMATCH),
3443 errmsg("inherited column \"%s\" has a generation conflict",
3444 attributeName)));
3445
3446 /*
3447 * Default and other constraints are handled by the caller.
3448 */
3449
3450 if (pg_add_s16_overflow(prevdef->inhcount, 1,
3451 &prevdef->inhcount))
3452 ereport(ERROR,
3453 errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3454 errmsg("too many inheritance parents"));
3455
3456 return prevdef;
3457}
3458
3459/*
3460 * StoreCatalogInheritance
3461 * Updates the system catalogs with proper inheritance information.
3462 *
3463 * supers is a list of the OIDs of the new relation's direct ancestors.
3464 */
3465static void
3467 bool child_is_partition)
3468{
3469 Relation relation;
3470 int32 seqNumber;
3471 ListCell *entry;
3472
3473 /*
3474 * sanity checks
3475 */
3476 Assert(OidIsValid(relationId));
3477
3478 if (supers == NIL)
3479 return;
3480
3481 /*
3482 * Store INHERITS information in pg_inherits using direct ancestors only.
3483 * Also enter dependencies on the direct ancestors, and make sure they are
3484 * marked with relhassubclass = true.
3485 *
3486 * (Once upon a time, both direct and indirect ancestors were found here
3487 * and then entered into pg_ipl. Since that catalog doesn't exist
3488 * anymore, there's no need to look for indirect ancestors.)
3489 */
3490 relation = table_open(InheritsRelationId, RowExclusiveLock);
3491
3492 seqNumber = 1;
3493 foreach(entry, supers)
3494 {
3495 Oid parentOid = lfirst_oid(entry);
3496
3497 StoreCatalogInheritance1(relationId, parentOid, seqNumber, relation,
3498 child_is_partition);
3499 seqNumber++;
3500 }
3501
3502 table_close(relation, RowExclusiveLock);
3503}
3504
3505/*
3506 * Make catalog entries showing relationId as being an inheritance child
3507 * of parentOid. inhRelation is the already-opened pg_inherits catalog.
3508 */
3509static void
3510StoreCatalogInheritance1(Oid relationId, Oid parentOid,
3511 int32 seqNumber, Relation inhRelation,
3512 bool child_is_partition)
3513{
3514 ObjectAddress childobject,
3515 parentobject;
3516
3517 /* store the pg_inherits row */
3518 StoreSingleInheritance(relationId, parentOid, seqNumber);
3519
3520 /*
3521 * Store a dependency too
3522 */
3523 parentobject.classId = RelationRelationId;
3524 parentobject.objectId = parentOid;
3525 parentobject.objectSubId = 0;
3526 childobject.classId = RelationRelationId;
3527 childobject.objectId = relationId;
3528 childobject.objectSubId = 0;
3529
3530 recordDependencyOn(&childobject, &parentobject,
3531 child_dependency_type(child_is_partition));
3532
3533 /*
3534 * Post creation hook of this inheritance. Since object_access_hook
3535 * doesn't take multiple object identifiers, we relay oid of parent
3536 * relation using auxiliary_id argument.
3537 */
3538 InvokeObjectPostAlterHookArg(InheritsRelationId,
3539 relationId, 0,
3540 parentOid, false);
3541
3542 /*
3543 * Mark the parent as having subclasses.
3544 */
3545 SetRelationHasSubclass(parentOid, true);
3546}
3547
3548/*
3549 * Look for an existing column entry with the given name.
3550 *
3551 * Returns the index (starting with 1) if attribute already exists in columns,
3552 * 0 if it doesn't.
3553 */
3554static int
3555findAttrByName(const char *attributeName, const List *columns)
3556{
3557 ListCell *lc;
3558 int i = 1;
3559
3560 foreach(lc, columns)
3561 {
3562 if (strcmp(attributeName, lfirst_node(ColumnDef, lc)->colname) == 0)
3563 return i;
3564
3565 i++;
3566 }
3567 return 0;
3568}
3569
3570
3571/*
3572 * SetRelationHasSubclass
3573 * Set the value of the relation's relhassubclass field in pg_class.
3574 *
3575 * It's always safe to set this field to true, because all SQL commands are
3576 * ready to see true and then find no children. On the other hand, commands
3577 * generally assume zero children if this is false.
3578 *
3579 * Caller must hold any self-exclusive lock until end of transaction. If the
3580 * new value is false, caller must have acquired that lock before reading the
3581 * evidence that justified the false value. That way, it properly waits if
3582 * another backend is simultaneously concluding no need to change the tuple
3583 * (new and old values are true).
3584 *
3585 * NOTE: an important side-effect of this operation is that an SI invalidation
3586 * message is sent out to all backends --- including me --- causing plans
3587 * referencing the relation to be rebuilt with the new list of children.
3588 * This must happen even if we find that no change is needed in the pg_class
3589 * row.
3590 */
3591void
3592SetRelationHasSubclass(Oid relationId, bool relhassubclass)
3593{
3594 Relation relationRelation;
3595 HeapTuple tuple;
3596 Form_pg_class classtuple;
3597
3599 ShareUpdateExclusiveLock, false) ||
3600 CheckRelationOidLockedByMe(relationId,
3601 ShareRowExclusiveLock, true));
3602
3603 /*
3604 * Fetch a modifiable copy of the tuple, modify it, update pg_class.
3605 */
3606 relationRelation = table_open(RelationRelationId, RowExclusiveLock);
3607 tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
3608 if (!HeapTupleIsValid(tuple))
3609 elog(ERROR, "cache lookup failed for relation %u", relationId);
3610 classtuple = (Form_pg_class) GETSTRUCT(tuple);
3611
3612 if (classtuple->relhassubclass != relhassubclass)
3613 {
3614 classtuple->relhassubclass = relhassubclass;
3615 CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
3616 }
3617 else
3618 {
3619 /* no need to change tuple, but force relcache rebuild anyway */
3621 }
3622
3623 heap_freetuple(tuple);
3624 table_close(relationRelation, RowExclusiveLock);
3625}
3626
3627/*
3628 * CheckRelationTableSpaceMove
3629 * Check if relation can be moved to new tablespace.
3630 *
3631 * NOTE: The caller must hold AccessExclusiveLock on the relation.
3632 *
3633 * Returns true if the relation can be moved to the new tablespace; raises
3634 * an error if it is not possible to do the move; returns false if the move
3635 * would have no effect.
3636 */
3637bool
3639{
3640 Oid oldTableSpaceId;
3641
3642 /*
3643 * No work if no change in tablespace. Note that MyDatabaseTableSpace is
3644 * stored as 0.
3645 */
3646 oldTableSpaceId = rel->rd_rel->reltablespace;
3647 if (newTableSpaceId == oldTableSpaceId ||
3648 (newTableSpaceId == MyDatabaseTableSpace && oldTableSpaceId == 0))
3649 return false;
3650
3651 /*
3652 * We cannot support moving mapped relations into different tablespaces.
3653 * (In particular this eliminates all shared catalogs.)
3654 */
3655 if (RelationIsMapped(rel))
3656 ereport(ERROR,
3657 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3658 errmsg("cannot move system relation \"%s\"",
3660
3661 /* Cannot move a non-shared relation into pg_global */
3662 if (newTableSpaceId == GLOBALTABLESPACE_OID)
3663 ereport(ERROR,
3664 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3665 errmsg("only shared relations can be placed in pg_global tablespace")));
3666
3667 /*
3668 * Do not allow moving temp tables of other backends ... their local
3669 * buffer manager is not going to cope.
3670 */
3671 if (RELATION_IS_OTHER_TEMP(rel))
3672 ereport(ERROR,
3673 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3674 errmsg("cannot move temporary tables of other sessions")));
3675
3676 return true;
3677}
3678
3679/*
3680 * SetRelationTableSpace
3681 * Set new reltablespace and relfilenumber in pg_class entry.
3682 *
3683 * newTableSpaceId is the new tablespace for the relation, and
3684 * newRelFilenumber its new filenumber. If newRelFilenumber is
3685 * InvalidRelFileNumber, this field is not updated.
3686 *
3687 * NOTE: The caller must hold AccessExclusiveLock on the relation.
3688 *
3689 * The caller of this routine had better check if a relation can be
3690 * moved to this new tablespace by calling CheckRelationTableSpaceMove()
3691 * first, and is responsible for making the change visible with
3692 * CommandCounterIncrement().
3693 */
3694void
3696 Oid newTableSpaceId,
3697 RelFileNumber newRelFilenumber)
3698{
3699 Relation pg_class;
3700 HeapTuple tuple;
3701 ItemPointerData otid;
3702 Form_pg_class rd_rel;
3703 Oid reloid = RelationGetRelid(rel);
3704
3705 Assert(CheckRelationTableSpaceMove(rel, newTableSpaceId));
3706
3707 /* Get a modifiable copy of the relation's pg_class row. */
3708 pg_class = table_open(RelationRelationId, RowExclusiveLock);
3709
3710 tuple = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(reloid));
3711 if (!HeapTupleIsValid(tuple))
3712 elog(ERROR, "cache lookup failed for relation %u", reloid);
3713 otid = tuple->t_self;
3714 rd_rel = (Form_pg_class) GETSTRUCT(tuple);
3715
3716 /* Update the pg_class row. */
3717 rd_rel->reltablespace = (newTableSpaceId == MyDatabaseTableSpace) ?
3718 InvalidOid : newTableSpaceId;
3719 if (RelFileNumberIsValid(newRelFilenumber))
3720 rd_rel->relfilenode = newRelFilenumber;
3721 CatalogTupleUpdate(pg_class, &otid, tuple);
3722 UnlockTuple(pg_class, &otid, InplaceUpdateTupleLock);
3723
3724 /*
3725 * Record dependency on tablespace. This is only required for relations
3726 * that have no physical storage.
3727 */
3728 if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
3729 changeDependencyOnTablespace(RelationRelationId, reloid,
3730 rd_rel->reltablespace);
3731
3732 heap_freetuple(tuple);
3733 table_close(pg_class, RowExclusiveLock);
3734}
3735
3736/*
3737 * renameatt_check - basic sanity checks before attribute rename
3738 */
3739static void
3740renameatt_check(Oid myrelid, Form_pg_class classform, bool recursing)
3741{
3742 char relkind = classform->relkind;
3743
3744 if (classform->reloftype && !recursing)
3745 ereport(ERROR,
3746 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3747 errmsg("cannot rename column of typed table")));
3748
3749 /*
3750 * Renaming the columns of sequences or toast tables doesn't actually
3751 * break anything from the system's point of view, since internal
3752 * references are by attnum. But it doesn't seem right to allow users to
3753 * change names that are hardcoded into the system, hence the following
3754 * restriction.
3755 */
3756 if (relkind != RELKIND_RELATION &&
3757 relkind != RELKIND_VIEW &&
3758 relkind != RELKIND_MATVIEW &&
3759 relkind != RELKIND_COMPOSITE_TYPE &&
3760 relkind != RELKIND_INDEX &&
3761 relkind != RELKIND_PARTITIONED_INDEX &&
3762 relkind != RELKIND_FOREIGN_TABLE &&
3763 relkind != RELKIND_PARTITIONED_TABLE)
3764 ereport(ERROR,
3765 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3766 errmsg("cannot rename columns of relation \"%s\"",
3767 NameStr(classform->relname)),
3769
3770 /*
3771 * permissions checking. only the owner of a class can change its schema.
3772 */
3773 if (!object_ownercheck(RelationRelationId, myrelid, GetUserId()))
3775 NameStr(classform->relname));
3776 if (!allowSystemTableMods && IsSystemClass(myrelid, classform))
3777 ereport(ERROR,
3778 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3779 errmsg("permission denied: \"%s\" is a system catalog",
3780 NameStr(classform->relname))));
3781}
3782
3783/*
3784 * renameatt_internal - workhorse for renameatt
3785 *
3786 * Return value is the attribute number in the 'myrelid' relation.
3787 */
3788static AttrNumber
3790 const char *oldattname,
3791 const char *newattname,
3792 bool recurse,
3793 bool recursing,
3794 int expected_parents,
3795 DropBehavior behavior)
3796{
3797 Relation targetrelation;
3798 Relation attrelation;
3799 HeapTuple atttup;
3800 Form_pg_attribute attform;
3802
3803 /*
3804 * Grab an exclusive lock on the target table, which we will NOT release
3805 * until end of transaction.
3806 */
3807 targetrelation = relation_open(myrelid, AccessExclusiveLock);
3808 renameatt_check(myrelid, RelationGetForm(targetrelation), recursing);
3809
3810 /*
3811 * if the 'recurse' flag is set then we are supposed to rename this
3812 * attribute in all classes that inherit from 'relname' (as well as in
3813 * 'relname').
3814 *
3815 * any permissions or problems with duplicate attributes will cause the
3816 * whole transaction to abort, which is what we want -- all or nothing.
3817 */
3818 if (recurse)
3819 {
3820 List *child_oids,
3821 *child_numparents;
3822 ListCell *lo,
3823 *li;
3824
3825 /*
3826 * we need the number of parents for each child so that the recursive
3827 * calls to renameatt() can determine whether there are any parents
3828 * outside the inheritance hierarchy being processed.
3829 */
3830 child_oids = find_all_inheritors(myrelid, AccessExclusiveLock,
3831 &child_numparents);
3832
3833 /*
3834 * find_all_inheritors does the recursive search of the inheritance
3835 * hierarchy, so all we have to do is process all of the relids in the
3836 * list that it returns.
3837 */
3838 forboth(lo, child_oids, li, child_numparents)
3839 {
3840 Oid childrelid = lfirst_oid(lo);
3841 int numparents = lfirst_int(li);
3842
3843 if (childrelid == myrelid)
3844 continue;
3845 /* note we need not recurse again */
3846 renameatt_internal(childrelid, oldattname, newattname, false, true, numparents, behavior);
3847 }
3848 }
3849 else
3850 {
3851 /*
3852 * If we are told not to recurse, there had better not be any child
3853 * tables; else the rename would put them out of step.
3854 *
3855 * expected_parents will only be 0 if we are not already recursing.
3856 */
3857 if (expected_parents == 0 &&
3859 ereport(ERROR,
3860 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3861 errmsg("inherited column \"%s\" must be renamed in child tables too",
3862 oldattname)));
3863 }
3864
3865 /* rename attributes in typed tables of composite type */
3866 if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
3867 {
3868 List *child_oids;
3869 ListCell *lo;
3870
3871 child_oids = find_typed_table_dependencies(targetrelation->rd_rel->reltype,
3872 RelationGetRelationName(targetrelation),
3873 behavior);
3874
3875 foreach(lo, child_oids)
3876 renameatt_internal(lfirst_oid(lo), oldattname, newattname, true, true, 0, behavior);
3877 }
3878
3879 attrelation = table_open(AttributeRelationId, RowExclusiveLock);
3880
3881 atttup = SearchSysCacheCopyAttName(myrelid, oldattname);
3882 if (!HeapTupleIsValid(atttup))
3883 ereport(ERROR,
3884 (errcode(ERRCODE_UNDEFINED_COLUMN),
3885 errmsg("column \"%s\" does not exist",
3886 oldattname)));
3887 attform = (Form_pg_attribute) GETSTRUCT(atttup);
3888
3889 attnum = attform->attnum;
3890 if (attnum <= 0)
3891 ereport(ERROR,
3892 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3893 errmsg("cannot rename system column \"%s\"",
3894 oldattname)));
3895
3896 /*
3897 * if the attribute is inherited, forbid the renaming. if this is a
3898 * top-level call to renameatt(), then expected_parents will be 0, so the
3899 * effect of this code will be to prohibit the renaming if the attribute
3900 * is inherited at all. if this is a recursive call to renameatt(),
3901 * expected_parents will be the number of parents the current relation has
3902 * within the inheritance hierarchy being processed, so we'll prohibit the
3903 * renaming only if there are additional parents from elsewhere.
3904 */
3905 if (attform->attinhcount > expected_parents)
3906 ereport(ERROR,
3907 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3908 errmsg("cannot rename inherited column \"%s\"",
3909 oldattname)));
3910
3911 /* new name should not already exist */
3912 (void) check_for_column_name_collision(targetrelation, newattname, false);
3913
3914 /* apply the update */
3915 namestrcpy(&(attform->attname), newattname);
3916
3917 CatalogTupleUpdate(attrelation, &atttup->t_self, atttup);
3918
3919 InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
3920
3921 heap_freetuple(atttup);
3922
3923 table_close(attrelation, RowExclusiveLock);
3924
3925 relation_close(targetrelation, NoLock); /* close rel but keep lock */
3926
3927 return attnum;
3928}
3929
3930/*
3931 * Perform permissions and integrity checks before acquiring a relation lock.
3932 */
3933static void
3935 void *arg)
3936{
3937 HeapTuple tuple;
3938 Form_pg_class form;
3939
3940 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
3941 if (!HeapTupleIsValid(tuple))
3942 return; /* concurrently dropped */
3943 form = (Form_pg_class) GETSTRUCT(tuple);
3944 renameatt_check(relid, form, false);
3945 ReleaseSysCache(tuple);
3946}
3947
3948/*
3949 * renameatt - changes the name of an attribute in a relation
3950 *
3951 * The returned ObjectAddress is that of the renamed column.
3952 */
3955{
3956 Oid relid;
3958 ObjectAddress address;
3959
3960 /* lock level taken here should match renameatt_internal */
3962 stmt->missing_ok ? RVR_MISSING_OK : 0,
3964 NULL);
3965
3966 if (!OidIsValid(relid))
3967 {
3969 (errmsg("relation \"%s\" does not exist, skipping",
3970 stmt->relation->relname)));
3971 return InvalidObjectAddress;
3972 }
3973
3974 attnum =
3975 renameatt_internal(relid,
3976 stmt->subname, /* old att name */
3977 stmt->newname, /* new att name */
3978 stmt->relation->inh, /* recursive? */
3979 false, /* recursing? */
3980 0, /* expected inhcount */
3981 stmt->behavior);
3982
3983 ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
3984
3985 return address;
3986}
3987
3988/*
3989 * same logic as renameatt_internal
3990 */
3991static ObjectAddress
3993 Oid mytypid,
3994 const char *oldconname,
3995 const char *newconname,
3996 bool recurse,
3997 bool recursing,
3998 int expected_parents)
3999{
4000 Relation targetrelation = NULL;
4001 Oid constraintOid;
4002 HeapTuple tuple;
4004 ObjectAddress address;
4005
4006 Assert(!myrelid || !mytypid);
4007
4008 if (mytypid)
4009 {
4010 constraintOid = get_domain_constraint_oid(mytypid, oldconname, false);
4011 }
4012 else
4013 {
4014 targetrelation = relation_open(myrelid, AccessExclusiveLock);
4015
4016 /*
4017 * don't tell it whether we're recursing; we allow changing typed
4018 * tables here
4019 */
4020 renameatt_check(myrelid, RelationGetForm(targetrelation), false);
4021
4022 constraintOid = get_relation_constraint_oid(myrelid, oldconname, false);
4023 }
4024
4025 tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
4026 if (!HeapTupleIsValid(tuple))
4027 elog(ERROR, "cache lookup failed for constraint %u",
4028 constraintOid);
4029 con = (Form_pg_constraint) GETSTRUCT(tuple);
4030
4031 if (myrelid &&
4032 (con->contype == CONSTRAINT_CHECK ||
4033 con->contype == CONSTRAINT_NOTNULL) &&
4034 !con->connoinherit)
4035 {
4036 if (recurse)
4037 {
4038 List *child_oids,
4039 *child_numparents;
4040 ListCell *lo,
4041 *li;
4042
4043 child_oids = find_all_inheritors(myrelid, AccessExclusiveLock,
4044 &child_numparents);
4045
4046 forboth(lo, child_oids, li, child_numparents)
4047 {
4048 Oid childrelid = lfirst_oid(lo);
4049 int numparents = lfirst_int(li);
4050
4051 if (childrelid == myrelid)
4052 continue;
4053
4054 rename_constraint_internal(childrelid, InvalidOid, oldconname, newconname, false, true, numparents);
4055 }
4056 }
4057 else
4058 {
4059 if (expected_parents == 0 &&
4061 ereport(ERROR,
4062 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
4063 errmsg("inherited constraint \"%s\" must be renamed in child tables too",
4064 oldconname)));
4065 }
4066
4067 if (con->coninhcount > expected_parents)
4068 ereport(ERROR,
4069 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
4070 errmsg("cannot rename inherited constraint \"%s\"",
4071 oldconname)));
4072 }
4073
4074 if (con->conindid
4075 && (con->contype == CONSTRAINT_PRIMARY
4076 || con->contype == CONSTRAINT_UNIQUE
4077 || con->contype == CONSTRAINT_EXCLUSION))
4078 /* rename the index; this renames the constraint as well */
4079 RenameRelationInternal(con->conindid, newconname, false, true);
4080 else
4081 RenameConstraintById(constraintOid, newconname);
4082
4083 ObjectAddressSet(address, ConstraintRelationId, constraintOid);
4084
4085 ReleaseSysCache(tuple);
4086
4087 if (targetrelation)
4088 {
4089 /*
4090 * Invalidate relcache so as others can see the new constraint name.
4091 */
4092 CacheInvalidateRelcache(targetrelation);
4093
4094 relation_close(targetrelation, NoLock); /* close rel but keep lock */
4095 }
4096
4097 return address;
4098}
4099
4102{
4103 Oid relid = InvalidOid;
4104 Oid typid = InvalidOid;
4105
4106 if (stmt->renameType == OBJECT_DOMCONSTRAINT)
4107 {
4108 Relation rel;
4109 HeapTuple tup;
4110
4111 typid = typenameTypeId(NULL, makeTypeNameFromNameList(castNode(List, stmt->object)));
4112 rel = table_open(TypeRelationId, RowExclusiveLock);
4113 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
4114 if (!HeapTupleIsValid(tup))
4115 elog(ERROR, "cache lookup failed for type %u", typid);
4116 checkDomainOwner(tup);
4117 ReleaseSysCache(tup);
4118 table_close(rel, NoLock);
4119 }
4120 else
4121 {
4122 /* lock level taken here should match rename_constraint_internal */
4124 stmt->missing_ok ? RVR_MISSING_OK : 0,
4126 NULL);
4127 if (!OidIsValid(relid))
4128 {
4130 (errmsg("relation \"%s\" does not exist, skipping",
4131 stmt->relation->relname)));
4132 return InvalidObjectAddress;
4133 }
4134 }
4135
4136 return
4137 rename_constraint_internal(relid, typid,
4138 stmt->subname,
4139 stmt->newname,
4140 (stmt->relation &&
4141 stmt->relation->inh), /* recursive? */
4142 false, /* recursing? */
4143 0 /* expected inhcount */ );
4144}
4145
4146/*
4147 * Execute ALTER TABLE/INDEX/SEQUENCE/VIEW/MATERIALIZED VIEW/FOREIGN TABLE
4148 * RENAME
4149 */
4152{
4153 bool is_index_stmt = stmt->renameType == OBJECT_INDEX;
4154 Oid relid;
4155 ObjectAddress address;
4156
4157 /*
4158 * Grab an exclusive lock on the target table, index, sequence, view,
4159 * materialized view, or foreign table, which we will NOT release until
4160 * end of transaction.
4161 *
4162 * Lock level used here should match RenameRelationInternal, to avoid lock
4163 * escalation. However, because ALTER INDEX can be used with any relation
4164 * type, we mustn't believe without verification.
4165 */
4166 for (;;)
4167 {
4168 LOCKMODE lockmode;
4169 char relkind;
4170 bool obj_is_index;
4171
4172 lockmode = is_index_stmt ? ShareUpdateExclusiveLock : AccessExclusiveLock;
4173
4174 relid = RangeVarGetRelidExtended(stmt->relation, lockmode,
4175 stmt->missing_ok ? RVR_MISSING_OK : 0,
4177 stmt);
4178
4179 if (!OidIsValid(relid))
4180 {
4182 (errmsg("relation \"%s\" does not exist, skipping",
4183 stmt->relation->relname)));
4184 return InvalidObjectAddress;
4185 }
4186
4187 /*
4188 * We allow mismatched statement and object types (e.g., ALTER INDEX
4189 * to rename a table), but we might've used the wrong lock level. If
4190 * that happens, retry with the correct lock level. We don't bother
4191 * if we already acquired AccessExclusiveLock with an index, however.
4192 */
4193 relkind = get_rel_relkind(relid);
4194 obj_is_index = (relkind == RELKIND_INDEX ||
4195 relkind == RELKIND_PARTITIONED_INDEX);
4196 if (obj_is_index || is_index_stmt == obj_is_index)
4197 break;
4198
4199 UnlockRelationOid(relid, lockmode);
4200 is_index_stmt = obj_is_index;
4201 }
4202
4203 /* Do the work */
4204 RenameRelationInternal(relid, stmt->newname, false, is_index_stmt);
4205
4206 ObjectAddressSet(address, RelationRelationId, relid);
4207
4208 return address;
4209}
4210
4211/*
4212 * RenameRelationInternal - change the name of a relation
4213 */
4214void
4215RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bool is_index)
4216{
4217 Relation targetrelation;
4218 Relation relrelation; /* for RELATION relation */
4219 ItemPointerData otid;
4220 HeapTuple reltup;
4221 Form_pg_class relform;
4222 Oid namespaceId;
4223
4224 /*
4225 * Grab a lock on the target relation, which we will NOT release until end
4226 * of transaction. We need at least a self-exclusive lock so that
4227 * concurrent DDL doesn't overwrite the rename if they start updating
4228 * while still seeing the old version. The lock also guards against
4229 * triggering relcache reloads in concurrent sessions, which might not
4230 * handle this information changing under them. For indexes, we can use a
4231 * reduced lock level because RelationReloadIndexInfo() handles indexes
4232 * specially.
4233 */
4234 targetrelation = relation_open(myrelid, is_index ? ShareUpdateExclusiveLock : AccessExclusiveLock);
4235 namespaceId = RelationGetNamespace(targetrelation);
4236
4237 /*
4238 * Find relation's pg_class tuple, and make sure newrelname isn't in use.
4239 */
4240 relrelation = table_open(RelationRelationId, RowExclusiveLock);
4241
4242 reltup = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(myrelid));
4243 if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
4244 elog(ERROR, "cache lookup failed for relation %u", myrelid);
4245 otid = reltup->t_self;
4246 relform = (Form_pg_class) GETSTRUCT(reltup);
4247
4248 if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
4249 ereport(ERROR,
4250 (errcode(ERRCODE_DUPLICATE_TABLE),
4251 errmsg("relation \"%s\" already exists",
4252 newrelname)));
4253
4254 /*
4255 * RenameRelation is careful not to believe the caller's idea of the
4256 * relation kind being handled. We don't have to worry about this, but
4257 * let's not be totally oblivious to it. We can process an index as
4258 * not-an-index, but not the other way around.
4259 */
4260 Assert(!is_index ||
4261 is_index == (targetrelation->rd_rel->relkind == RELKIND_INDEX ||
4262 targetrelation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX));
4263
4264 /*
4265 * Update pg_class tuple with new relname. (Scribbling on reltup is OK
4266 * because it's a copy...)
4267 */
4268 namestrcpy(&(relform->relname), newrelname);
4269
4270 CatalogTupleUpdate(relrelation, &otid, reltup);
4271 UnlockTuple(relrelation, &otid, InplaceUpdateTupleLock);
4272
4273 InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0,
4274 InvalidOid, is_internal);
4275
4276 heap_freetuple(reltup);
4277 table_close(relrelation, RowExclusiveLock);
4278
4279 /*
4280 * Also rename the associated type, if any.
4281 */
4282 if (OidIsValid(targetrelation->rd_rel->reltype))
4283 RenameTypeInternal(targetrelation->rd_rel->reltype,
4284 newrelname, namespaceId);
4285
4286 /*
4287 * Also rename the associated constraint, if any.
4288 */
4289 if (targetrelation->rd_rel->relkind == RELKIND_INDEX ||
4290 targetrelation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
4291 {
4292 Oid constraintId = get_index_constraint(myrelid);
4293
4294 if (OidIsValid(constraintId))
4295 RenameConstraintById(constraintId, newrelname);
4296 }
4297
4298 /*
4299 * Close rel, but keep lock!
4300 */
4301 relation_close(targetrelation, NoLock);
4302}
4303
4304/*
4305 * ResetRelRewrite - reset relrewrite
4306 */
4307void
4309{
4310 Relation relrelation; /* for RELATION relation */
4311 HeapTuple reltup;
4312 Form_pg_class relform;
4313
4314 /*
4315 * Find relation's pg_class tuple.
4316 */
4317 relrelation = table_open(RelationRelationId, RowExclusiveLock);
4318
4319 reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
4320 if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
4321 elog(ERROR, "cache lookup failed for relation %u", myrelid);
4322 relform = (Form_pg_class) GETSTRUCT(reltup);
4323
4324 /*
4325 * Update pg_class tuple.
4326 */
4327 relform->relrewrite = InvalidOid;
4328
4329 CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
4330
4331 heap_freetuple(reltup);
4332 table_close(relrelation, RowExclusiveLock);
4333}
4334
4335/*
4336 * Disallow ALTER TABLE (and similar commands) when the current backend has
4337 * any open reference to the target table besides the one just acquired by
4338 * the calling command; this implies there's an open cursor or active plan.
4339 * We need this check because our lock doesn't protect us against stomping
4340 * on our own foot, only other people's feet!
4341 *
4342 * For ALTER TABLE, the only case known to cause serious trouble is ALTER
4343 * COLUMN TYPE, and some changes are obviously pretty benign, so this could
4344 * possibly be relaxed to only error out for certain types of alterations.
4345 * But the use-case for allowing any of these things is not obvious, so we
4346 * won't work hard at it for now.
4347 *
4348 * We also reject these commands if there are any pending AFTER trigger events
4349 * for the rel. This is certainly necessary for the rewriting variants of
4350 * ALTER TABLE, because they don't preserve tuple TIDs and so the pending
4351 * events would try to fetch the wrong tuples. It might be overly cautious
4352 * in other cases, but again it seems better to err on the side of paranoia.
4353 *
4354 * REINDEX calls this with "rel" referencing the index to be rebuilt; here
4355 * we are worried about active indexscans on the index. The trigger-event
4356 * check can be skipped, since we are doing no damage to the parent table.
4357 *
4358 * The statement name (eg, "ALTER TABLE") is passed for use in error messages.
4359 */
4360void
4362{
4363 int expected_refcnt;
4364
4365 expected_refcnt = rel->rd_isnailed ? 2 : 1;
4366 if (rel->rd_refcnt != expected_refcnt)
4367 ereport(ERROR,
4368 (errcode(ERRCODE_OBJECT_IN_USE),
4369 /* translator: first %s is a SQL command, eg ALTER TABLE */
4370 errmsg("cannot %s \"%s\" because it is being used by active queries in this session",
4372
4373 if (rel->rd_rel->relkind != RELKIND_INDEX &&
4374 rel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX &&
4376 ereport(ERROR,
4377 (errcode(ERRCODE_OBJECT_IN_USE),
4378 /* translator: first %s is a SQL command, eg ALTER TABLE */
4379 errmsg("cannot %s \"%s\" because it has pending trigger events",
4381}
4382
4383/*
4384 * CheckAlterTableIsSafe
4385 * Verify that it's safe to allow ALTER TABLE on this relation.
4386 *
4387 * This consists of CheckTableNotInUse() plus a check that the relation
4388 * isn't another session's temp table. We must split out the temp-table
4389 * check because there are callers of CheckTableNotInUse() that don't want
4390 * that, notably DROP TABLE. (We must allow DROP or we couldn't clean out
4391 * an orphaned temp schema.) Compare truncate_check_activity().
4392 */
4393static void
4395{
4396 /*
4397 * Don't allow ALTER on temp tables of other backends. Their local buffer
4398 * manager is not going to cope if we need to change the table's contents.
4399 * Even if we don't, there may be optimizations that assume temp tables
4400 * aren't subject to such interference.
4401 */
4402 if (RELATION_IS_OTHER_TEMP(rel))
4403 ereport(ERROR,
4404 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4405 errmsg("cannot alter temporary tables of other sessions")));
4406
4407 /*
4408 * Also check for active uses of the relation in the current transaction,
4409 * including open scans and pending AFTER trigger events.
4410 */
4411 CheckTableNotInUse(rel, "ALTER TABLE");
4412}
4413
4414/*
4415 * AlterTableLookupRelation
4416 * Look up, and lock, the OID for the relation named by an alter table
4417 * statement.
4418 */
4419Oid
4421{
4422 return RangeVarGetRelidExtended(stmt->relation, lockmode,
4423 stmt->missing_ok ? RVR_MISSING_OK : 0,
4425 stmt);
4426}
4427
4428/*
4429 * AlterTable
4430 * Execute ALTER TABLE, which can be a list of subcommands
4431 *
4432 * ALTER TABLE is performed in three phases:
4433 * 1. Examine subcommands and perform pre-transformation checking.
4434 * 2. Validate and transform subcommands, and update system catalogs.
4435 * 3. Scan table(s) to check new constraints, and optionally recopy
4436 * the data into new table(s).
4437 * Phase 3 is not performed unless one or more of the subcommands requires
4438 * it. The intention of this design is to allow multiple independent
4439 * updates of the table schema to be performed with only one pass over the
4440 * data.
4441 *
4442 * ATPrepCmd performs phase 1. A "work queue" entry is created for
4443 * each table to be affected (there may be multiple affected tables if the
4444 * commands traverse a table inheritance hierarchy). Also we do preliminary
4445 * validation of the subcommands. Because earlier subcommands may change
4446 * the catalog state seen by later commands, there are limits to what can
4447 * be done in this phase. Generally, this phase acquires table locks,
4448 * checks permissions and relkind, and recurses to find child tables.
4449 *
4450 * ATRewriteCatalogs performs phase 2 for each affected table.
4451 * Certain subcommands need to be performed before others to avoid
4452 * unnecessary conflicts; for example, DROP COLUMN should come before
4453 * ADD COLUMN. Therefore phase 1 divides the subcommands into multiple
4454 * lists, one for each logical "pass" of phase 2.
4455 *
4456 * ATRewriteTables performs phase 3 for those tables that need it.
4457 *
4458 * For most subcommand types, phases 2 and 3 do no explicit recursion,
4459 * since phase 1 already does it. However, for certain subcommand types
4460 * it is only possible to determine how to recurse at phase 2 time; for
4461 * those cases, phase 1 sets the cmd->recurse flag.
4462 *
4463 * Thanks to the magic of MVCC, an error anywhere along the way rolls back
4464 * the whole operation; we don't have to do anything special to clean up.
4465 *
4466 * The caller must lock the relation, with an appropriate lock level
4467 * for the subcommands requested, using AlterTableGetLockLevel(stmt->cmds)
4468 * or higher. We pass the lock level down
4469 * so that we can apply it recursively to inherited tables. Note that the
4470 * lock level we want as we recurse might well be higher than required for
4471 * that specific subcommand. So we pass down the overall lock requirement,
4472 * rather than reassess it at lower levels.
4473 *
4474 * The caller also provides a "context" which is to be passed back to
4475 * utility.c when we need to execute a subcommand such as CREATE INDEX.
4476 * Some of the fields therein, such as the relid, are used here as well.
4477 */
4478void
4480 AlterTableUtilityContext *context)
4481{
4482 Relation rel;
4483
4484 /* Caller is required to provide an adequate lock. */
4485 rel = relation_open(context->relid, NoLock);
4486
4488
4489 ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode, context);
4490}
4491
4492/*
4493 * AlterTableInternal
4494 *
4495 * ALTER TABLE with target specified by OID
4496 *
4497 * We do not reject if the relation is already open, because it's quite
4498 * likely that one or more layers of caller have it open. That means it
4499 * is unsafe to use this entry point for alterations that could break
4500 * existing query plans. On the assumption it's not used for such, we
4501 * don't have to reject pending AFTER triggers, either.
4502 *
4503 * Also, since we don't have an AlterTableUtilityContext, this cannot be
4504 * used for any subcommand types that require parse transformation or
4505 * could generate subcommands that have to be passed to ProcessUtility.
4506 */
4507void
4508AlterTableInternal(Oid relid, List *cmds, bool recurse)
4509{
4510 Relation rel;
4511 LOCKMODE lockmode = AlterTableGetLockLevel(cmds);
4512
4513 rel = relation_open(relid, lockmode);
4514
4516
4517 ATController(NULL, rel, cmds, recurse, lockmode, NULL);
4518}
4519
4520/*
4521 * AlterTableGetLockLevel
4522 *
4523 * Sets the overall lock level required for the supplied list of subcommands.
4524 * Policy for doing this set according to needs of AlterTable(), see
4525 * comments there for overall explanation.
4526 *
4527 * Function is called before and after parsing, so it must give same
4528 * answer each time it is called. Some subcommands are transformed
4529 * into other subcommand types, so the transform must never be made to a
4530 * lower lock level than previously assigned. All transforms are noted below.
4531 *
4532 * Since this is called before we lock the table we cannot use table metadata
4533 * to influence the type of lock we acquire.
4534 *
4535 * There should be no lockmodes hardcoded into the subcommand functions. All
4536 * lockmode decisions for ALTER TABLE are made here only. The one exception is
4537 * ALTER TABLE RENAME which is treated as a different statement type T_RenameStmt
4538 * and does not travel through this section of code and cannot be combined with
4539 * any of the subcommands given here.
4540 *
4541 * Note that Hot Standby only knows about AccessExclusiveLocks on the primary
4542 * so any changes that might affect SELECTs running on standbys need to use
4543 * AccessExclusiveLocks even if you think a lesser lock would do, unless you
4544 * have a solution for that also.
4545 *
4546 * Also note that pg_dump uses only an AccessShareLock, meaning that anything
4547 * that takes a lock less than AccessExclusiveLock can change object definitions
4548 * while pg_dump is running. Be careful to check that the appropriate data is
4549 * derived by pg_dump using an MVCC snapshot, rather than syscache lookups,
4550 * otherwise we might end up with an inconsistent dump that can't restore.
4551 */
4554{
4555 /*
4556 * This only works if we read catalog tables using MVCC snapshots.
4557 */
4558 ListCell *lcmd;
4560
4561 foreach(lcmd, cmds)
4562 {
4563 AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
4564 LOCKMODE cmd_lockmode = AccessExclusiveLock; /* default for compiler */
4565
4566 switch (cmd->subtype)
4567 {
4568 /*
4569 * These subcommands rewrite the heap, so require full locks.
4570 */
4571 case AT_AddColumn: /* may rewrite heap, in some cases and visible
4572 * to SELECT */
4573 case AT_SetAccessMethod: /* must rewrite heap */
4574 case AT_SetTableSpace: /* must rewrite heap */
4575 case AT_AlterColumnType: /* must rewrite heap */
4576 cmd_lockmode = AccessExclusiveLock;
4577 break;
4578
4579 /*
4580 * These subcommands may require addition of toast tables. If
4581 * we add a toast table to a table currently being scanned, we
4582 * might miss data added to the new toast table by concurrent
4583 * insert transactions.
4584 */
4585 case AT_SetStorage: /* may add toast tables, see
4586 * ATRewriteCatalogs() */
4587 cmd_lockmode = AccessExclusiveLock;
4588 break;
4589
4590 /*
4591 * Removing constraints can affect SELECTs that have been
4592 * optimized assuming the constraint holds true. See also
4593 * CloneFkReferenced.
4594 */
4595 case AT_DropConstraint: /* as DROP INDEX */
4596 case AT_DropNotNull: /* may change some SQL plans */
4597 cmd_lockmode = AccessExclusiveLock;
4598 break;
4599
4600 /*
4601 * Subcommands that may be visible to concurrent SELECTs
4602 */
4603 case AT_DropColumn: /* change visible to SELECT */
4604 case AT_AddColumnToView: /* CREATE VIEW */
4605 case AT_DropOids: /* used to equiv to DropColumn */
4606 case AT_EnableAlwaysRule: /* may change SELECT rules */
4607 case AT_EnableReplicaRule: /* may change SELECT rules */
4608 case AT_EnableRule: /* may change SELECT rules */
4609 case AT_DisableRule: /* may change SELECT rules */
4610 cmd_lockmode = AccessExclusiveLock;
4611 break;
4612
4613 /*
4614 * Changing owner may remove implicit SELECT privileges
4615 */
4616 case AT_ChangeOwner: /* change visible to SELECT */
4617 cmd_lockmode = AccessExclusiveLock;
4618 break;
4619
4620 /*
4621 * Changing foreign table options may affect optimization.
4622 */
4623 case AT_GenericOptions:
4625 cmd_lockmode = AccessExclusiveLock;
4626 break;
4627
4628 /*
4629 * These subcommands affect write operations only.
4630 */
4631 case AT_EnableTrig:
4634 case AT_EnableTrigAll:
4635 case AT_EnableTrigUser:
4636 case AT_DisableTrig:
4637 case AT_DisableTrigAll:
4638 case AT_DisableTrigUser:
4639 cmd_lockmode = ShareRowExclusiveLock;
4640 break;
4641
4642 /*
4643 * These subcommands affect write operations only. XXX
4644 * Theoretically, these could be ShareRowExclusiveLock.
4645 */
4646 case AT_ColumnDefault:
4648 case AT_AlterConstraint:
4649 case AT_AddIndex: /* from ADD CONSTRAINT */
4651 case AT_ReplicaIdentity:
4652 case AT_SetNotNull:
4657 case AT_AddIdentity:
4658 case AT_DropIdentity:
4659 case AT_SetIdentity:
4660 case AT_SetExpression:
4661 case AT_DropExpression:
4662 case AT_SetCompression:
4663 cmd_lockmode = AccessExclusiveLock;
4664 break;
4665
4666 case AT_AddConstraint:
4667 case AT_ReAddConstraint: /* becomes AT_AddConstraint */
4668 case AT_ReAddDomainConstraint: /* becomes AT_AddConstraint */
4669 if (IsA(cmd->def, Constraint))
4670 {
4671 Constraint *con = (Constraint *) cmd->def;
4672
4673 switch (con->contype)
4674 {
4675 case CONSTR_EXCLUSION:
4676 case CONSTR_PRIMARY:
4677 case CONSTR_UNIQUE:
4678
4679 /*
4680 * Cases essentially the same as CREATE INDEX. We
4681 * could reduce the lock strength to ShareLock if
4682 * we can work out how to allow concurrent catalog
4683 * updates. XXX Might be set down to
4684 * ShareRowExclusiveLock but requires further
4685 * analysis.
4686 */
4687 cmd_lockmode = AccessExclusiveLock;
4688 break;
4689 case CONSTR_FOREIGN:
4690
4691 /*
4692 * We add triggers to both tables when we add a
4693 * Foreign Key, so the lock level must be at least
4694 * as strong as CREATE TRIGGER.
4695 */
4696 cmd_lockmode = ShareRowExclusiveLock;
4697 break;
4698
4699 default:
4700 cmd_lockmode = AccessExclusiveLock;
4701 }
4702 }
4703 break;
4704
4705 /*
4706 * These subcommands affect inheritance behaviour. Queries
4707 * started before us will continue to see the old inheritance
4708 * behaviour, while queries started after we commit will see
4709 * new behaviour. No need to prevent reads or writes to the
4710 * subtable while we hook it up though. Changing the TupDesc
4711 * may be a problem, so keep highest lock.
4712 */
4713 case AT_AddInherit:
4714 case AT_DropInherit:
4715 cmd_lockmode = AccessExclusiveLock;
4716 break;
4717
4718 /*
4719 * These subcommands affect implicit row type conversion. They
4720 * have affects similar to CREATE/DROP CAST on queries. don't
4721 * provide for invalidating parse trees as a result of such
4722 * changes, so we keep these at AccessExclusiveLock.
4723 */
4724 case AT_AddOf:
4725 case AT_DropOf:
4726 cmd_lockmode = AccessExclusiveLock;
4727 break;
4728
4729 /*
4730 * Only used by CREATE OR REPLACE VIEW which must conflict
4731 * with an SELECTs currently using the view.
4732 */
4734 cmd_lockmode = AccessExclusiveLock;
4735 break;
4736
4737 /*
4738 * These subcommands affect general strategies for performance
4739 * and maintenance, though don't change the semantic results
4740 * from normal data reads and writes. Delaying an ALTER TABLE
4741 * behind currently active writes only delays the point where
4742 * the new strategy begins to take effect, so there is no
4743 * benefit in waiting. In this case the minimum restriction
4744 * applies: we don't currently allow concurrent catalog
4745 * updates.
4746 */
4747 case AT_SetStatistics: /* Uses MVCC in getTableAttrs() */
4748 case AT_ClusterOn: /* Uses MVCC in getIndexes() */
4749 case AT_DropCluster: /* Uses MVCC in getIndexes() */
4750 case AT_SetOptions: /* Uses MVCC in getTableAttrs() */
4751 case AT_ResetOptions: /* Uses MVCC in getTableAttrs() */
4752 cmd_lockmode = ShareUpdateExclusiveLock;
4753 break;
4754
4755 case AT_SetLogged:
4756 case AT_SetUnLogged:
4757 cmd_lockmode = AccessExclusiveLock;
4758 break;
4759
4760 case AT_ValidateConstraint: /* Uses MVCC in getConstraints() */
4761 cmd_lockmode = ShareUpdateExclusiveLock;
4762 break;
4763
4764 /*
4765 * Rel options are more complex than first appears. Options
4766 * are set here for tables, views and indexes; for historical
4767 * reasons these can all be used with ALTER TABLE, so we can't
4768 * decide between them using the basic grammar.
4769 */
4770 case AT_SetRelOptions: /* Uses MVCC in getIndexes() and
4771 * getTables() */
4772 case AT_ResetRelOptions: /* Uses MVCC in getIndexes() and
4773 * getTables() */
4774 cmd_lockmode = AlterTableGetRelOptionsLockLevel((List *) cmd->def);
4775 break;
4776
4777 case AT_AttachPartition:
4778 cmd_lockmode = ShareUpdateExclusiveLock;
4779 break;
4780
4781 case AT_DetachPartition:
4782 if (((PartitionCmd *) cmd->def)->concurrent)
4783 cmd_lockmode = ShareUpdateExclusiveLock;
4784 else
4785 cmd_lockmode = AccessExclusiveLock;
4786 break;
4787
4789 cmd_lockmode = ShareUpdateExclusiveLock;
4790 break;
4791
4792 default: /* oops */
4793 elog(ERROR, "unrecognized alter table type: %d",
4794 (int) cmd->subtype);
4795 break;
4796 }
4797
4798 /*
4799 * Take the greatest lockmode from any subcommand
4800 */
4801 if (cmd_lockmode > lockmode)
4802 lockmode = cmd_lockmode;
4803 }
4804
4805 return lockmode;
4806}
4807
4808/*
4809 * ATController provides top level control over the phases.
4810 *
4811 * parsetree is passed in to allow it to be passed to event triggers
4812 * when requested.
4813 */
4814static void
4816 Relation rel, List *cmds, bool recurse, LOCKMODE lockmode,
4817 AlterTableUtilityContext *context)
4818{
4819 List *wqueue = NIL;
4820 ListCell *lcmd;
4821
4822 /* Phase 1: preliminary examination of commands, create work queue */
4823 foreach(lcmd, cmds)
4824 {
4825 AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
4826
4827 ATPrepCmd(&wqueue, rel, cmd, recurse, false, lockmode, context);
4828 }
4829
4830 /* Close the relation, but keep lock until commit */
4831 relation_close(rel, NoLock);
4832
4833 /* Phase 2: update system catalogs */
4834 ATRewriteCatalogs(&wqueue, lockmode, context);
4835
4836 /* Phase 3: scan/rewrite tables as needed, and run afterStmts */
4837 ATRewriteTables(parsetree, &wqueue, lockmode, context);
4838}
4839
4840/*
4841 * ATPrepCmd
4842 *
4843 * Traffic cop for ALTER TABLE Phase 1 operations, including simple
4844 * recursion and permission checks.
4845 *
4846 * Caller must have acquired appropriate lock type on relation already.
4847 * This lock should be held until commit.
4848 */
4849static void
4851 bool recurse, bool recursing, LOCKMODE lockmode,
4852 AlterTableUtilityContext *context)
4853{
4854 AlteredTableInfo *tab;
4856
4857 /* Find or create work queue entry for this table */
4858 tab = ATGetQueueEntry(wqueue, rel);
4859
4860 /*
4861 * Disallow any ALTER TABLE other than ALTER TABLE DETACH FINALIZE on
4862 * partitions that are pending detach.
4863 */
4864 if (rel->rd_rel->relispartition &&
4867 ereport(ERROR,
4868 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4869 errmsg("cannot alter partition \"%s\" with an incomplete detach",
4871 errhint("Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending detach operation."));
4872
4873 /*
4874 * Copy the original subcommand for each table, so we can scribble on it.
4875 * This avoids conflicts when different child tables need to make
4876 * different parse transformations (for example, the same column may have
4877 * different column numbers in different children).
4878 */
4879 cmd = copyObject(cmd);
4880
4881 /*
4882 * Do permissions and relkind checking, recursion to child tables if
4883 * needed, and any additional phase-1 processing needed. (But beware of
4884 * adding any processing that looks at table details that another
4885 * subcommand could change. In some cases we reject multiple subcommands
4886 * that could try to change the same state in contrary ways.)
4887 */
4888 switch (cmd->subtype)
4889 {
4890 case AT_AddColumn: /* ADD COLUMN */
4891 ATSimplePermissions(cmd->subtype, rel,
4894 ATPrepAddColumn(wqueue, rel, recurse, recursing, false, cmd,
4895 lockmode, context);
4896 /* Recursion occurs during execution phase */
4897 pass = AT_PASS_ADD_COL;
4898 break;
4899 case AT_AddColumnToView: /* add column via CREATE OR REPLACE VIEW */
4901 ATPrepAddColumn(wqueue, rel, recurse, recursing, true, cmd,
4902 lockmode, context);
4903 /* Recursion occurs during execution phase */
4904 pass = AT_PASS_ADD_COL;
4905 break;
4906 case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */
4907
4908 /*
4909 * We allow defaults on views so that INSERT into a view can have
4910 * default-ish behavior. This works because the rewriter
4911 * substitutes default values into INSERTs before it expands
4912 * rules.
4913 */
4914 ATSimplePermissions(cmd->subtype, rel,
4917 ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4918 /* No command-specific prep needed */
4920 break;
4921 case AT_CookedColumnDefault: /* add a pre-cooked default */
4922 /* This is currently used only in CREATE TABLE */
4923 /* (so the permission check really isn't necessary) */
4924 ATSimplePermissions(cmd->subtype, rel,
4926 /* This command never recurses */
4928 break;
4929 case AT_AddIdentity:
4930 ATSimplePermissions(cmd->subtype, rel,
4933 /* Set up recursion for phase 2; no other prep needed */
4934 if (recurse)
4935 cmd->recurse = true;
4937 break;
4938 case AT_SetIdentity:
4939 ATSimplePermissions(cmd->subtype, rel,
4942 /* Set up recursion for phase 2; no other prep needed */
4943 if (recurse)
4944 cmd->recurse = true;
4945 /* This should run after AddIdentity, so do it in MISC pass */
4946 pass = AT_PASS_MISC;
4947 break;
4948 case AT_DropIdentity:
4949 ATSimplePermissions(cmd->subtype, rel,
4952 /* Set up recursion for phase 2; no other prep needed */
4953 if (recurse)
4954 cmd->recurse = true;
4955 pass = AT_PASS_DROP;
4956 break;
4957 case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
4958 ATSimplePermissions(cmd->subtype, rel,
4960 /* Set up recursion for phase 2; no other prep needed */
4961 if (recurse)
4962 cmd->recurse = true;
4963 pass = AT_PASS_DROP;
4964 break;
4965 case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
4966 ATSimplePermissions(cmd->subtype, rel,
4968 /* Set up recursion for phase 2; no other prep needed */
4969 if (recurse)
4970 cmd->recurse = true;
4971 pass = AT_PASS_COL_ATTRS;
4972 break;
4973 case AT_SetExpression: /* ALTER COLUMN SET EXPRESSION */
4974 ATSimplePermissions(cmd->subtype, rel,
4976 ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4978 break;
4979 case AT_DropExpression: /* ALTER COLUMN DROP EXPRESSION */
4980 ATSimplePermissions(cmd->subtype, rel,
4982 ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4983 ATPrepDropExpression(rel, cmd, recurse, recursing, lockmode);
4984 pass = AT_PASS_DROP;
4985 break;
4986 case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */
4987 ATSimplePermissions(cmd->subtype, rel,
4990 ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4991 /* No command-specific prep needed */
4992 pass = AT_PASS_MISC;
4993 break;
4994 case AT_SetOptions: /* ALTER COLUMN SET ( options ) */
4995 case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */
4996 ATSimplePermissions(cmd->subtype, rel,
4999 /* This command never recurses */
5000 pass = AT_PASS_MISC;
5001 break;
5002 case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
5003 ATSimplePermissions(cmd->subtype, rel,
5006 ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
5007 /* No command-specific prep needed */
5008 pass = AT_PASS_MISC;
5009 break;
5010 case AT_SetCompression: /* ALTER COLUMN SET COMPRESSION */
5011 ATSimplePermissions(cmd->subtype, rel,
5013 /* This command never recurses */
5014 /* No command-specific prep needed */
5015 pass = AT_PASS_MISC;
5016 break;
5017 case AT_DropColumn: /* DROP COLUMN */
5018 ATSimplePermissions(cmd->subtype, rel,
5021 ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd,
5022 lockmode, context);
5023 /* Recursion occurs during execution phase */
5024 pass = AT_PASS_DROP;