PostgreSQL Source Code  git master
indexcmds.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * indexcmds.c
4  * POSTGRES define and remove index code.
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/commands/indexcmds.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include "access/amapi.h"
19 #include "access/gist.h"
20 #include "access/heapam.h"
21 #include "access/htup_details.h"
22 #include "access/reloptions.h"
23 #include "access/sysattr.h"
24 #include "access/tableam.h"
25 #include "access/xact.h"
26 #include "catalog/catalog.h"
27 #include "catalog/index.h"
28 #include "catalog/indexing.h"
29 #include "catalog/namespace.h"
30 #include "catalog/pg_am.h"
31 #include "catalog/pg_authid.h"
32 #include "catalog/pg_constraint.h"
33 #include "catalog/pg_database.h"
34 #include "catalog/pg_inherits.h"
35 #include "catalog/pg_namespace.h"
36 #include "catalog/pg_opclass.h"
37 #include "catalog/pg_opfamily.h"
38 #include "catalog/pg_tablespace.h"
39 #include "catalog/pg_type.h"
40 #include "commands/comment.h"
41 #include "commands/dbcommands.h"
42 #include "commands/defrem.h"
43 #include "commands/event_trigger.h"
44 #include "commands/progress.h"
45 #include "commands/tablecmds.h"
46 #include "commands/tablespace.h"
47 #include "mb/pg_wchar.h"
48 #include "miscadmin.h"
49 #include "nodes/makefuncs.h"
50 #include "nodes/nodeFuncs.h"
51 #include "optimizer/optimizer.h"
52 #include "parser/parse_coerce.h"
53 #include "parser/parse_oper.h"
54 #include "partitioning/partdesc.h"
55 #include "pgstat.h"
56 #include "rewrite/rewriteManip.h"
57 #include "storage/lmgr.h"
58 #include "storage/proc.h"
59 #include "storage/procarray.h"
60 #include "storage/sinvaladt.h"
61 #include "utils/acl.h"
62 #include "utils/builtins.h"
63 #include "utils/fmgroids.h"
64 #include "utils/guc.h"
65 #include "utils/injection_point.h"
66 #include "utils/inval.h"
67 #include "utils/lsyscache.h"
68 #include "utils/memutils.h"
69 #include "utils/partcache.h"
70 #include "utils/pg_rusage.h"
71 #include "utils/regproc.h"
72 #include "utils/snapmgr.h"
73 #include "utils/syscache.h"
74 
75 
76 /* non-export function prototypes */
77 static bool CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts);
78 static void CheckPredicate(Expr *predicate);
79 static void ComputeIndexAttrs(IndexInfo *indexInfo,
80  Oid *typeOids,
81  Oid *collationOids,
82  Oid *opclassOids,
83  Datum *opclassOptions,
84  int16 *colOptions,
85  const List *attList,
86  const List *exclusionOpNames,
87  Oid relId,
88  const char *accessMethodName,
89  Oid accessMethodId,
90  bool amcanorder,
91  bool isconstraint,
92  bool iswithoutoverlaps,
93  Oid ddl_userid,
94  int ddl_sec_context,
95  int *ddl_save_nestlevel);
96 static char *ChooseIndexName(const char *tabname, Oid namespaceId,
97  const List *colnames, const List *exclusionOpNames,
98  bool primary, bool isconstraint);
99 static char *ChooseIndexNameAddition(const List *colnames);
100 static List *ChooseIndexColumnNames(const List *indexElems);
101 static void ReindexIndex(const ReindexStmt *stmt, const ReindexParams *params,
102  bool isTopLevel);
103 static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
104  Oid relId, Oid oldRelId, void *arg);
105 static Oid ReindexTable(const ReindexStmt *stmt, const ReindexParams *params,
106  bool isTopLevel);
107 static void ReindexMultipleTables(const ReindexStmt *stmt,
108  const ReindexParams *params);
109 static void reindex_error_callback(void *arg);
110 static void ReindexPartitions(const ReindexStmt *stmt, Oid relid,
111  const ReindexParams *params, bool isTopLevel);
112 static void ReindexMultipleInternal(const ReindexStmt *stmt, const List *relids,
113  const ReindexParams *params);
114 static bool ReindexRelationConcurrently(const ReindexStmt *stmt,
115  Oid relationOid,
116  const ReindexParams *params);
117 static void update_relispartition(Oid relationId, bool newval);
118 static inline void set_indexsafe_procflags(void);
119 
120 /*
121  * callback argument type for RangeVarCallbackForReindexIndex()
122  */
124 {
125  ReindexParams params; /* options from statement */
126  Oid locked_table_oid; /* tracks previously locked table */
127 };
128 
129 /*
130  * callback arguments for reindex_error_callback()
131  */
132 typedef struct ReindexErrorInfo
133 {
134  char *relname;
136  char relkind;
138 
139 /*
140  * CheckIndexCompatible
141  * Determine whether an existing index definition is compatible with a
142  * prospective index definition, such that the existing index storage
143  * could become the storage of the new index, avoiding a rebuild.
144  *
145  * 'oldId': the OID of the existing index
146  * 'accessMethodName': name of the AM to use.
147  * 'attributeList': a list of IndexElem specifying columns and expressions
148  * to index on.
149  * 'exclusionOpNames': list of names of exclusion-constraint operators,
150  * or NIL if not an exclusion constraint.
151  * 'isWithoutOverlaps': true iff this index has a WITHOUT OVERLAPS clause.
152  *
153  * This is tailored to the needs of ALTER TABLE ALTER TYPE, which recreates
154  * any indexes that depended on a changing column from their pg_get_indexdef
155  * or pg_get_constraintdef definitions. We omit some of the sanity checks of
156  * DefineIndex. We assume that the old and new indexes have the same number
157  * of columns and that if one has an expression column or predicate, both do.
158  * Errors arising from the attribute list still apply.
159  *
160  * Most column type changes that can skip a table rewrite do not invalidate
161  * indexes. We acknowledge this when all operator classes, collations and
162  * exclusion operators match. Though we could further permit intra-opfamily
163  * changes for btree and hash indexes, that adds subtle complexity with no
164  * concrete benefit for core types. Note, that INCLUDE columns aren't
165  * checked by this function, for them it's enough that table rewrite is
166  * skipped.
167  *
168  * When a comparison or exclusion operator has a polymorphic input type, the
169  * actual input types must also match. This defends against the possibility
170  * that operators could vary behavior in response to get_fn_expr_argtype().
171  * At present, this hazard is theoretical: check_exclusion_constraint() and
172  * all core index access methods decline to set fn_expr for such calls.
173  *
174  * We do not yet implement a test to verify compatibility of expression
175  * columns or predicates, so assume any such index is incompatible.
176  */
177 bool
179  const char *accessMethodName,
180  const List *attributeList,
181  const List *exclusionOpNames,
182  bool isWithoutOverlaps)
183 {
184  bool isconstraint;
185  Oid *typeIds;
186  Oid *collationIds;
187  Oid *opclassIds;
188  Datum *opclassOptions;
189  Oid accessMethodId;
190  Oid relationId;
191  HeapTuple tuple;
192  Form_pg_index indexForm;
193  Form_pg_am accessMethodForm;
194  IndexAmRoutine *amRoutine;
195  bool amcanorder;
196  bool amsummarizing;
197  int16 *coloptions;
198  IndexInfo *indexInfo;
199  int numberOfAttributes;
200  int old_natts;
201  bool ret = true;
202  oidvector *old_indclass;
203  oidvector *old_indcollation;
204  Relation irel;
205  int i;
206  Datum d;
207 
208  /* Caller should already have the relation locked in some way. */
209  relationId = IndexGetRelation(oldId, false);
210 
211  /*
212  * We can pretend isconstraint = false unconditionally. It only serves to
213  * decide the text of an error message that should never happen for us.
214  */
215  isconstraint = false;
216 
217  numberOfAttributes = list_length(attributeList);
218  Assert(numberOfAttributes > 0);
219  Assert(numberOfAttributes <= INDEX_MAX_KEYS);
220 
221  /* look up the access method */
222  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
223  if (!HeapTupleIsValid(tuple))
224  ereport(ERROR,
225  (errcode(ERRCODE_UNDEFINED_OBJECT),
226  errmsg("access method \"%s\" does not exist",
227  accessMethodName)));
228  accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
229  accessMethodId = accessMethodForm->oid;
230  amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
231  ReleaseSysCache(tuple);
232 
233  amcanorder = amRoutine->amcanorder;
234  amsummarizing = amRoutine->amsummarizing;
235 
236  /*
237  * Compute the operator classes, collations, and exclusion operators for
238  * the new index, so we can test whether it's compatible with the existing
239  * one. Note that ComputeIndexAttrs might fail here, but that's OK:
240  * DefineIndex would have failed later. Our attributeList contains only
241  * key attributes, thus we're filling ii_NumIndexAttrs and
242  * ii_NumIndexKeyAttrs with same value.
243  */
244  indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
245  accessMethodId, NIL, NIL, false, false,
246  false, false, amsummarizing, isWithoutOverlaps);
247  typeIds = palloc_array(Oid, numberOfAttributes);
248  collationIds = palloc_array(Oid, numberOfAttributes);
249  opclassIds = palloc_array(Oid, numberOfAttributes);
250  opclassOptions = palloc_array(Datum, numberOfAttributes);
251  coloptions = palloc_array(int16, numberOfAttributes);
252  ComputeIndexAttrs(indexInfo,
253  typeIds, collationIds, opclassIds, opclassOptions,
254  coloptions, attributeList,
255  exclusionOpNames, relationId,
256  accessMethodName, accessMethodId,
257  amcanorder, isconstraint, isWithoutOverlaps, InvalidOid,
258  0, NULL);
259 
260  /* Get the soon-obsolete pg_index tuple. */
261  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(oldId));
262  if (!HeapTupleIsValid(tuple))
263  elog(ERROR, "cache lookup failed for index %u", oldId);
264  indexForm = (Form_pg_index) GETSTRUCT(tuple);
265 
266  /*
267  * We don't assess expressions or predicates; assume incompatibility.
268  * Also, if the index is invalid for any reason, treat it as incompatible.
269  */
270  if (!(heap_attisnull(tuple, Anum_pg_index_indpred, NULL) &&
271  heap_attisnull(tuple, Anum_pg_index_indexprs, NULL) &&
272  indexForm->indisvalid))
273  {
274  ReleaseSysCache(tuple);
275  return false;
276  }
277 
278  /* Any change in operator class or collation breaks compatibility. */
279  old_natts = indexForm->indnkeyatts;
280  Assert(old_natts == numberOfAttributes);
281 
282  d = SysCacheGetAttrNotNull(INDEXRELID, tuple, Anum_pg_index_indcollation);
283  old_indcollation = (oidvector *) DatumGetPointer(d);
284 
285  d = SysCacheGetAttrNotNull(INDEXRELID, tuple, Anum_pg_index_indclass);
286  old_indclass = (oidvector *) DatumGetPointer(d);
287 
288  ret = (memcmp(old_indclass->values, opclassIds, old_natts * sizeof(Oid)) == 0 &&
289  memcmp(old_indcollation->values, collationIds, old_natts * sizeof(Oid)) == 0);
290 
291  ReleaseSysCache(tuple);
292 
293  if (!ret)
294  return false;
295 
296  /* For polymorphic opcintype, column type changes break compatibility. */
297  irel = index_open(oldId, AccessShareLock); /* caller probably has a lock */
298  for (i = 0; i < old_natts; i++)
299  {
300  if (IsPolymorphicType(get_opclass_input_type(opclassIds[i])) &&
301  TupleDescAttr(irel->rd_att, i)->atttypid != typeIds[i])
302  {
303  ret = false;
304  break;
305  }
306  }
307 
308  /* Any change in opclass options break compatibility. */
309  if (ret)
310  {
311  Datum *oldOpclassOptions = palloc_array(Datum, old_natts);
312 
313  for (i = 0; i < old_natts; i++)
314  oldOpclassOptions[i] = get_attoptions(oldId, i + 1);
315 
316  ret = CompareOpclassOptions(oldOpclassOptions, opclassOptions, old_natts);
317 
318  pfree(oldOpclassOptions);
319  }
320 
321  /* Any change in exclusion operator selections breaks compatibility. */
322  if (ret && indexInfo->ii_ExclusionOps != NULL)
323  {
324  Oid *old_operators,
325  *old_procs;
326  uint16 *old_strats;
327 
328  RelationGetExclusionInfo(irel, &old_operators, &old_procs, &old_strats);
329  ret = memcmp(old_operators, indexInfo->ii_ExclusionOps,
330  old_natts * sizeof(Oid)) == 0;
331 
332  /* Require an exact input type match for polymorphic operators. */
333  if (ret)
334  {
335  for (i = 0; i < old_natts && ret; i++)
336  {
337  Oid left,
338  right;
339 
340  op_input_types(indexInfo->ii_ExclusionOps[i], &left, &right);
341  if ((IsPolymorphicType(left) || IsPolymorphicType(right)) &&
342  TupleDescAttr(irel->rd_att, i)->atttypid != typeIds[i])
343  {
344  ret = false;
345  break;
346  }
347  }
348  }
349  }
350 
351  index_close(irel, NoLock);
352  return ret;
353 }
354 
355 /*
356  * CompareOpclassOptions
357  *
358  * Compare per-column opclass options which are represented by arrays of text[]
359  * datums. Both elements of arrays and array themselves can be NULL.
360  */
361 static bool
362 CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts)
363 {
364  int i;
365 
366  if (!opts1 && !opts2)
367  return true;
368 
369  for (i = 0; i < natts; i++)
370  {
371  Datum opt1 = opts1 ? opts1[i] : (Datum) 0;
372  Datum opt2 = opts2 ? opts2[i] : (Datum) 0;
373 
374  if (opt1 == (Datum) 0)
375  {
376  if (opt2 == (Datum) 0)
377  continue;
378  else
379  return false;
380  }
381  else if (opt2 == (Datum) 0)
382  return false;
383 
384  /* Compare non-NULL text[] datums. */
385  if (!DatumGetBool(DirectFunctionCall2(array_eq, opt1, opt2)))
386  return false;
387  }
388 
389  return true;
390 }
391 
392 /*
393  * WaitForOlderSnapshots
394  *
395  * Wait for transactions that might have an older snapshot than the given xmin
396  * limit, because it might not contain tuples deleted just before it has
397  * been taken. Obtain a list of VXIDs of such transactions, and wait for them
398  * individually. This is used when building an index concurrently.
399  *
400  * We can exclude any running transactions that have xmin > the xmin given;
401  * their oldest snapshot must be newer than our xmin limit.
402  * We can also exclude any transactions that have xmin = zero, since they
403  * evidently have no live snapshot at all (and any one they might be in
404  * process of taking is certainly newer than ours). Transactions in other
405  * DBs can be ignored too, since they'll never even be able to see the
406  * index being worked on.
407  *
408  * We can also exclude autovacuum processes and processes running manual
409  * lazy VACUUMs, because they won't be fazed by missing index entries
410  * either. (Manual ANALYZEs, however, can't be excluded because they
411  * might be within transactions that are going to do arbitrary operations
412  * later.) Processes running CREATE INDEX CONCURRENTLY or REINDEX CONCURRENTLY
413  * on indexes that are neither expressional nor partial are also safe to
414  * ignore, since we know that those processes won't examine any data
415  * outside the table they're indexing.
416  *
417  * Also, GetCurrentVirtualXIDs never reports our own vxid, so we need not
418  * check for that.
419  *
420  * If a process goes idle-in-transaction with xmin zero, we do not need to
421  * wait for it anymore, per the above argument. We do not have the
422  * infrastructure right now to stop waiting if that happens, but we can at
423  * least avoid the folly of waiting when it is idle at the time we would
424  * begin to wait. We do this by repeatedly rechecking the output of
425  * GetCurrentVirtualXIDs. If, during any iteration, a particular vxid
426  * doesn't show up in the output, we know we can forget about it.
427  */
428 void
430 {
431  int n_old_snapshots;
432  int i;
433  VirtualTransactionId *old_snapshots;
434 
435  old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
437  | PROC_IN_SAFE_IC,
438  &n_old_snapshots);
439  if (progress)
441 
442  for (i = 0; i < n_old_snapshots; i++)
443  {
444  if (!VirtualTransactionIdIsValid(old_snapshots[i]))
445  continue; /* found uninteresting in previous cycle */
446 
447  if (i > 0)
448  {
449  /* see if anything's changed ... */
450  VirtualTransactionId *newer_snapshots;
451  int n_newer_snapshots;
452  int j;
453  int k;
454 
455  newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
456  true, false,
458  | PROC_IN_SAFE_IC,
459  &n_newer_snapshots);
460  for (j = i; j < n_old_snapshots; j++)
461  {
462  if (!VirtualTransactionIdIsValid(old_snapshots[j]))
463  continue; /* found uninteresting in previous cycle */
464  for (k = 0; k < n_newer_snapshots; k++)
465  {
466  if (VirtualTransactionIdEquals(old_snapshots[j],
467  newer_snapshots[k]))
468  break;
469  }
470  if (k >= n_newer_snapshots) /* not there anymore */
471  SetInvalidVirtualTransactionId(old_snapshots[j]);
472  }
473  pfree(newer_snapshots);
474  }
475 
476  if (VirtualTransactionIdIsValid(old_snapshots[i]))
477  {
478  /* If requested, publish who we're going to wait for. */
479  if (progress)
480  {
481  PGPROC *holder = ProcNumberGetProc(old_snapshots[i].procNumber);
482 
483  if (holder)
485  holder->pid);
486  }
487  VirtualXactLock(old_snapshots[i], true);
488  }
489 
490  if (progress)
492  }
493 }
494 
495 
496 /*
497  * DefineIndex
498  * Creates a new index.
499  *
500  * This function manages the current userid according to the needs of pg_dump.
501  * Recreating old-database catalog entries in new-database is fine, regardless
502  * of which users would have permission to recreate those entries now. That's
503  * just preservation of state. Running opaque expressions, like calling a
504  * function named in a catalog entry or evaluating a pg_node_tree in a catalog
505  * entry, as anyone other than the object owner, is not fine. To adhere to
506  * those principles and to remain fail-safe, use the table owner userid for
507  * most ACL checks. Use the original userid for ACL checks reached without
508  * traversing opaque expressions. (pg_dump can predict such ACL checks from
509  * catalogs.) Overall, this is a mess. Future DDL development should
510  * consider offering one DDL command for catalog setup and a separate DDL
511  * command for steps that run opaque expressions.
512  *
513  * 'tableId': the OID of the table relation on which the index is to be
514  * created
515  * 'stmt': IndexStmt describing the properties of the new index.
516  * 'indexRelationId': normally InvalidOid, but during bootstrap can be
517  * nonzero to specify a preselected OID for the index.
518  * 'parentIndexId': the OID of the parent index; InvalidOid if not the child
519  * of a partitioned index.
520  * 'parentConstraintId': the OID of the parent constraint; InvalidOid if not
521  * the child of a constraint (only used when recursing)
522  * 'total_parts': total number of direct and indirect partitions of relation;
523  * pass -1 if not known or rel is not partitioned.
524  * 'is_alter_table': this is due to an ALTER rather than a CREATE operation.
525  * 'check_rights': check for CREATE rights in namespace and tablespace. (This
526  * should be true except when ALTER is deleting/recreating an index.)
527  * 'check_not_in_use': check for table not already in use in current session.
528  * This should be true unless caller is holding the table open, in which
529  * case the caller had better have checked it earlier.
530  * 'skip_build': make the catalog entries but don't create the index files
531  * 'quiet': suppress the NOTICE chatter ordinarily provided for constraints.
532  *
533  * Returns the object address of the created index.
534  */
536 DefineIndex(Oid tableId,
537  IndexStmt *stmt,
538  Oid indexRelationId,
539  Oid parentIndexId,
540  Oid parentConstraintId,
541  int total_parts,
542  bool is_alter_table,
543  bool check_rights,
544  bool check_not_in_use,
545  bool skip_build,
546  bool quiet)
547 {
548  bool concurrent;
549  char *indexRelationName;
550  char *accessMethodName;
551  Oid *typeIds;
552  Oid *collationIds;
553  Oid *opclassIds;
554  Datum *opclassOptions;
555  Oid accessMethodId;
556  Oid namespaceId;
557  Oid tablespaceId;
558  Oid createdConstraintId = InvalidOid;
559  List *indexColNames;
560  List *allIndexParams;
561  Relation rel;
562  HeapTuple tuple;
563  Form_pg_am accessMethodForm;
564  IndexAmRoutine *amRoutine;
565  bool amcanorder;
566  bool amissummarizing;
567  amoptions_function amoptions;
568  bool exclusion;
569  bool partitioned;
570  bool safe_index;
571  Datum reloptions;
572  int16 *coloptions;
573  IndexInfo *indexInfo;
574  bits16 flags;
575  bits16 constr_flags;
576  int numberOfAttributes;
577  int numberOfKeyAttributes;
578  TransactionId limitXmin;
579  ObjectAddress address;
580  LockRelId heaprelid;
581  LOCKTAG heaplocktag;
582  LOCKMODE lockmode;
583  Snapshot snapshot;
584  Oid root_save_userid;
585  int root_save_sec_context;
586  int root_save_nestlevel;
587 
588  root_save_nestlevel = NewGUCNestLevel();
589 
591 
592  /*
593  * Some callers need us to run with an empty default_tablespace; this is a
594  * necessary hack to be able to reproduce catalog state accurately when
595  * recreating indexes after table-rewriting ALTER TABLE.
596  */
597  if (stmt->reset_default_tblspc)
598  (void) set_config_option("default_tablespace", "",
600  GUC_ACTION_SAVE, true, 0, false);
601 
602  /*
603  * Force non-concurrent build on temporary relations, even if CONCURRENTLY
604  * was requested. Other backends can't access a temporary relation, so
605  * there's no harm in grabbing a stronger lock, and a non-concurrent DROP
606  * is more efficient. Do this before any use of the concurrent option is
607  * done.
608  */
609  if (stmt->concurrent && get_rel_persistence(tableId) != RELPERSISTENCE_TEMP)
610  concurrent = true;
611  else
612  concurrent = false;
613 
614  /*
615  * Start progress report. If we're building a partition, this was already
616  * done.
617  */
618  if (!OidIsValid(parentIndexId))
619  {
622  concurrent ?
625  }
626 
627  /*
628  * No index OID to report yet
629  */
631  InvalidOid);
632 
633  /*
634  * count key attributes in index
635  */
636  numberOfKeyAttributes = list_length(stmt->indexParams);
637 
638  /*
639  * Calculate the new list of index columns including both key columns and
640  * INCLUDE columns. Later we can determine which of these are key
641  * columns, and which are just part of the INCLUDE list by checking the
642  * list position. A list item in a position less than ii_NumIndexKeyAttrs
643  * is part of the key columns, and anything equal to and over is part of
644  * the INCLUDE columns.
645  */
646  allIndexParams = list_concat_copy(stmt->indexParams,
647  stmt->indexIncludingParams);
648  numberOfAttributes = list_length(allIndexParams);
649 
650  if (numberOfKeyAttributes <= 0)
651  ereport(ERROR,
652  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
653  errmsg("must specify at least one column")));
654  if (numberOfAttributes > INDEX_MAX_KEYS)
655  ereport(ERROR,
656  (errcode(ERRCODE_TOO_MANY_COLUMNS),
657  errmsg("cannot use more than %d columns in an index",
658  INDEX_MAX_KEYS)));
659 
660  /*
661  * Only SELECT ... FOR UPDATE/SHARE are allowed while doing a standard
662  * index build; but for concurrent builds we allow INSERT/UPDATE/DELETE
663  * (but not VACUUM).
664  *
665  * NB: Caller is responsible for making sure that tableId refers to the
666  * relation on which the index should be built; except in bootstrap mode,
667  * this will typically require the caller to have already locked the
668  * relation. To avoid lock upgrade hazards, that lock should be at least
669  * as strong as the one we take here.
670  *
671  * NB: If the lock strength here ever changes, code that is run by
672  * parallel workers under the control of certain particular ambuild
673  * functions will need to be updated, too.
674  */
675  lockmode = concurrent ? ShareUpdateExclusiveLock : ShareLock;
676  rel = table_open(tableId, lockmode);
677 
678  /*
679  * Switch to the table owner's userid, so that any index functions are run
680  * as that user. Also lock down security-restricted operations. We
681  * already arranged to make GUC variable changes local to this command.
682  */
683  GetUserIdAndSecContext(&root_save_userid, &root_save_sec_context);
684  SetUserIdAndSecContext(rel->rd_rel->relowner,
685  root_save_sec_context | SECURITY_RESTRICTED_OPERATION);
686 
687  namespaceId = RelationGetNamespace(rel);
688 
689  /*
690  * It has exclusion constraint behavior if it's an EXCLUDE constraint or a
691  * temporal PRIMARY KEY/UNIQUE constraint
692  */
693  exclusion = stmt->excludeOpNames || stmt->iswithoutoverlaps;
694 
695  /* Ensure that it makes sense to index this kind of relation */
696  switch (rel->rd_rel->relkind)
697  {
698  case RELKIND_RELATION:
699  case RELKIND_MATVIEW:
700  case RELKIND_PARTITIONED_TABLE:
701  /* OK */
702  break;
703  default:
704  ereport(ERROR,
705  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
706  errmsg("cannot create index on relation \"%s\"",
708  errdetail_relkind_not_supported(rel->rd_rel->relkind)));
709  break;
710  }
711 
712  /*
713  * Establish behavior for partitioned tables, and verify sanity of
714  * parameters.
715  *
716  * We do not build an actual index in this case; we only create a few
717  * catalog entries. The actual indexes are built by recursing for each
718  * partition.
719  */
720  partitioned = rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
721  if (partitioned)
722  {
723  /*
724  * Note: we check 'stmt->concurrent' rather than 'concurrent', so that
725  * the error is thrown also for temporary tables. Seems better to be
726  * consistent, even though we could do it on temporary table because
727  * we're not actually doing it concurrently.
728  */
729  if (stmt->concurrent)
730  ereport(ERROR,
731  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
732  errmsg("cannot create index on partitioned table \"%s\" concurrently",
733  RelationGetRelationName(rel))));
734  }
735 
736  /*
737  * Don't try to CREATE INDEX on temp tables of other backends.
738  */
739  if (RELATION_IS_OTHER_TEMP(rel))
740  ereport(ERROR,
741  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
742  errmsg("cannot create indexes on temporary tables of other sessions")));
743 
744  /*
745  * Unless our caller vouches for having checked this already, insist that
746  * the table not be in use by our own session, either. Otherwise we might
747  * fail to make entries in the new index (for instance, if an INSERT or
748  * UPDATE is in progress and has already made its list of target indexes).
749  */
750  if (check_not_in_use)
751  CheckTableNotInUse(rel, "CREATE INDEX");
752 
753  /*
754  * Verify we (still) have CREATE rights in the rel's namespace.
755  * (Presumably we did when the rel was created, but maybe not anymore.)
756  * Skip check if caller doesn't want it. Also skip check if
757  * bootstrapping, since permissions machinery may not be working yet.
758  */
759  if (check_rights && !IsBootstrapProcessingMode())
760  {
761  AclResult aclresult;
762 
763  aclresult = object_aclcheck(NamespaceRelationId, namespaceId, root_save_userid,
764  ACL_CREATE);
765  if (aclresult != ACLCHECK_OK)
766  aclcheck_error(aclresult, OBJECT_SCHEMA,
767  get_namespace_name(namespaceId));
768  }
769 
770  /*
771  * Select tablespace to use. If not specified, use default tablespace
772  * (which may in turn default to database's default).
773  */
774  if (stmt->tableSpace)
775  {
776  tablespaceId = get_tablespace_oid(stmt->tableSpace, false);
777  if (partitioned && tablespaceId == MyDatabaseTableSpace)
778  ereport(ERROR,
779  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
780  errmsg("cannot specify default tablespace for partitioned relations")));
781  }
782  else
783  {
784  tablespaceId = GetDefaultTablespace(rel->rd_rel->relpersistence,
785  partitioned);
786  /* note InvalidOid is OK in this case */
787  }
788 
789  /* Check tablespace permissions */
790  if (check_rights &&
791  OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
792  {
793  AclResult aclresult;
794 
795  aclresult = object_aclcheck(TableSpaceRelationId, tablespaceId, root_save_userid,
796  ACL_CREATE);
797  if (aclresult != ACLCHECK_OK)
799  get_tablespace_name(tablespaceId));
800  }
801 
802  /*
803  * Force shared indexes into the pg_global tablespace. This is a bit of a
804  * hack but seems simpler than marking them in the BKI commands. On the
805  * other hand, if it's not shared, don't allow it to be placed there.
806  */
807  if (rel->rd_rel->relisshared)
808  tablespaceId = GLOBALTABLESPACE_OID;
809  else if (tablespaceId == GLOBALTABLESPACE_OID)
810  ereport(ERROR,
811  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
812  errmsg("only shared relations can be placed in pg_global tablespace")));
813 
814  /*
815  * Choose the index column names.
816  */
817  indexColNames = ChooseIndexColumnNames(allIndexParams);
818 
819  /*
820  * Select name for index if caller didn't specify
821  */
822  indexRelationName = stmt->idxname;
823  if (indexRelationName == NULL)
824  indexRelationName = ChooseIndexName(RelationGetRelationName(rel),
825  namespaceId,
826  indexColNames,
827  stmt->excludeOpNames,
828  stmt->primary,
829  stmt->isconstraint);
830 
831  /*
832  * look up the access method, verify it can handle the requested features
833  */
834  accessMethodName = stmt->accessMethod;
835  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
836  if (!HeapTupleIsValid(tuple))
837  {
838  /*
839  * Hack to provide more-or-less-transparent updating of old RTREE
840  * indexes to GiST: if RTREE is requested and not found, use GIST.
841  */
842  if (strcmp(accessMethodName, "rtree") == 0)
843  {
844  ereport(NOTICE,
845  (errmsg("substituting access method \"gist\" for obsolete method \"rtree\"")));
846  accessMethodName = "gist";
847  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
848  }
849 
850  if (!HeapTupleIsValid(tuple))
851  ereport(ERROR,
852  (errcode(ERRCODE_UNDEFINED_OBJECT),
853  errmsg("access method \"%s\" does not exist",
854  accessMethodName)));
855  }
856  accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
857  accessMethodId = accessMethodForm->oid;
858  amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
859 
861  accessMethodId);
862 
863  if (stmt->unique && !stmt->iswithoutoverlaps && !amRoutine->amcanunique)
864  ereport(ERROR,
865  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
866  errmsg("access method \"%s\" does not support unique indexes",
867  accessMethodName)));
868  if (stmt->indexIncludingParams != NIL && !amRoutine->amcaninclude)
869  ereport(ERROR,
870  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
871  errmsg("access method \"%s\" does not support included columns",
872  accessMethodName)));
873  if (numberOfKeyAttributes > 1 && !amRoutine->amcanmulticol)
874  ereport(ERROR,
875  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
876  errmsg("access method \"%s\" does not support multicolumn indexes",
877  accessMethodName)));
878  if (exclusion && amRoutine->amgettuple == NULL)
879  ereport(ERROR,
880  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
881  errmsg("access method \"%s\" does not support exclusion constraints",
882  accessMethodName)));
883  if (stmt->iswithoutoverlaps && strcmp(accessMethodName, "gist") != 0)
884  ereport(ERROR,
885  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
886  errmsg("access method \"%s\" does not support WITHOUT OVERLAPS constraints",
887  accessMethodName)));
888 
889  amcanorder = amRoutine->amcanorder;
890  amoptions = amRoutine->amoptions;
891  amissummarizing = amRoutine->amsummarizing;
892 
893  pfree(amRoutine);
894  ReleaseSysCache(tuple);
895 
896  /*
897  * Validate predicate, if given
898  */
899  if (stmt->whereClause)
900  CheckPredicate((Expr *) stmt->whereClause);
901 
902  /*
903  * Parse AM-specific options, convert to text array form, validate.
904  */
905  reloptions = transformRelOptions((Datum) 0, stmt->options,
906  NULL, NULL, false, false);
907 
908  (void) index_reloptions(amoptions, reloptions, true);
909 
910  /*
911  * Prepare arguments for index_create, primarily an IndexInfo structure.
912  * Note that predicates must be in implicit-AND format. In a concurrent
913  * build, mark it not-ready-for-inserts.
914  */
915  indexInfo = makeIndexInfo(numberOfAttributes,
916  numberOfKeyAttributes,
917  accessMethodId,
918  NIL, /* expressions, NIL for now */
919  make_ands_implicit((Expr *) stmt->whereClause),
920  stmt->unique,
921  stmt->nulls_not_distinct,
922  !concurrent,
923  concurrent,
924  amissummarizing,
925  stmt->iswithoutoverlaps);
926 
927  typeIds = palloc_array(Oid, numberOfAttributes);
928  collationIds = palloc_array(Oid, numberOfAttributes);
929  opclassIds = palloc_array(Oid, numberOfAttributes);
930  opclassOptions = palloc_array(Datum, numberOfAttributes);
931  coloptions = palloc_array(int16, numberOfAttributes);
932  ComputeIndexAttrs(indexInfo,
933  typeIds, collationIds, opclassIds, opclassOptions,
934  coloptions, allIndexParams,
935  stmt->excludeOpNames, tableId,
936  accessMethodName, accessMethodId,
937  amcanorder, stmt->isconstraint, stmt->iswithoutoverlaps,
938  root_save_userid, root_save_sec_context,
939  &root_save_nestlevel);
940 
941  /*
942  * Extra checks when creating a PRIMARY KEY index.
943  */
944  if (stmt->primary)
945  index_check_primary_key(rel, indexInfo, is_alter_table, stmt);
946 
947  /*
948  * If this table is partitioned and we're creating a unique index, primary
949  * key, or exclusion constraint, make sure that the partition key is a
950  * subset of the index's columns. Otherwise it would be possible to
951  * violate uniqueness by putting values that ought to be unique in
952  * different partitions.
953  *
954  * We could lift this limitation if we had global indexes, but those have
955  * their own problems, so this is a useful feature combination.
956  */
957  if (partitioned && (stmt->unique || exclusion))
958  {
960  const char *constraint_type;
961  int i;
962 
963  if (stmt->primary)
964  constraint_type = "PRIMARY KEY";
965  else if (stmt->unique)
966  constraint_type = "UNIQUE";
967  else if (stmt->excludeOpNames)
968  constraint_type = "EXCLUDE";
969  else
970  {
971  elog(ERROR, "unknown constraint type");
972  constraint_type = NULL; /* keep compiler quiet */
973  }
974 
975  /*
976  * Verify that all the columns in the partition key appear in the
977  * unique key definition, with the same notion of equality.
978  */
979  for (i = 0; i < key->partnatts; i++)
980  {
981  bool found = false;
982  int eq_strategy;
983  Oid ptkey_eqop;
984  int j;
985 
986  /*
987  * Identify the equality operator associated with this partkey
988  * column. For list and range partitioning, partkeys use btree
989  * operator classes; hash partitioning uses hash operator classes.
990  * (Keep this in sync with ComputePartitionAttrs!)
991  */
992  if (key->strategy == PARTITION_STRATEGY_HASH)
993  eq_strategy = HTEqualStrategyNumber;
994  else
995  eq_strategy = BTEqualStrategyNumber;
996 
997  ptkey_eqop = get_opfamily_member(key->partopfamily[i],
998  key->partopcintype[i],
999  key->partopcintype[i],
1000  eq_strategy);
1001  if (!OidIsValid(ptkey_eqop))
1002  elog(ERROR, "missing operator %d(%u,%u) in partition opfamily %u",
1003  eq_strategy, key->partopcintype[i], key->partopcintype[i],
1004  key->partopfamily[i]);
1005 
1006  /*
1007  * We'll need to be able to identify the equality operators
1008  * associated with index columns, too. We know what to do with
1009  * btree opclasses; if there are ever any other index types that
1010  * support unique indexes, this logic will need extension. But if
1011  * we have an exclusion constraint (or a temporal PK), it already
1012  * knows the operators, so we don't have to infer them.
1013  */
1014  if (stmt->unique && !stmt->iswithoutoverlaps && accessMethodId != BTREE_AM_OID)
1015  ereport(ERROR,
1016  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1017  errmsg("cannot match partition key to an index using access method \"%s\"",
1018  accessMethodName)));
1019 
1020  /*
1021  * It may be possible to support UNIQUE constraints when partition
1022  * keys are expressions, but is it worth it? Give up for now.
1023  */
1024  if (key->partattrs[i] == 0)
1025  ereport(ERROR,
1026  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1027  errmsg("unsupported %s constraint with partition key definition",
1028  constraint_type),
1029  errdetail("%s constraints cannot be used when partition keys include expressions.",
1030  constraint_type)));
1031 
1032  /* Search the index column(s) for a match */
1033  for (j = 0; j < indexInfo->ii_NumIndexKeyAttrs; j++)
1034  {
1035  if (key->partattrs[i] == indexInfo->ii_IndexAttrNumbers[j])
1036  {
1037  /*
1038  * Matched the column, now what about the collation and
1039  * equality op?
1040  */
1041  Oid idx_opfamily;
1042  Oid idx_opcintype;
1043 
1044  if (key->partcollation[i] != collationIds[j])
1045  continue;
1046 
1047  if (get_opclass_opfamily_and_input_type(opclassIds[j],
1048  &idx_opfamily,
1049  &idx_opcintype))
1050  {
1051  Oid idx_eqop = InvalidOid;
1052 
1053  if (stmt->unique && !stmt->iswithoutoverlaps)
1054  idx_eqop = get_opfamily_member(idx_opfamily,
1055  idx_opcintype,
1056  idx_opcintype,
1058  else if (exclusion)
1059  idx_eqop = indexInfo->ii_ExclusionOps[j];
1060  Assert(idx_eqop);
1061 
1062  if (ptkey_eqop == idx_eqop)
1063  {
1064  found = true;
1065  break;
1066  }
1067  else if (exclusion)
1068  {
1069  /*
1070  * We found a match, but it's not an equality
1071  * operator. Instead of failing below with an
1072  * error message about a missing column, fail now
1073  * and explain that the operator is wrong.
1074  */
1075  Form_pg_attribute att = TupleDescAttr(RelationGetDescr(rel), key->partattrs[i] - 1);
1076 
1077  ereport(ERROR,
1078  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1079  errmsg("cannot match partition key to index on column \"%s\" using non-equal operator \"%s\"",
1080  NameStr(att->attname),
1081  get_opname(indexInfo->ii_ExclusionOps[j]))));
1082  }
1083  }
1084  }
1085  }
1086 
1087  if (!found)
1088  {
1089  Form_pg_attribute att;
1090 
1091  att = TupleDescAttr(RelationGetDescr(rel),
1092  key->partattrs[i] - 1);
1093  ereport(ERROR,
1094  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1095  errmsg("unique constraint on partitioned table must include all partitioning columns"),
1096  errdetail("%s constraint on table \"%s\" lacks column \"%s\" which is part of the partition key.",
1097  constraint_type, RelationGetRelationName(rel),
1098  NameStr(att->attname))));
1099  }
1100  }
1101  }
1102 
1103 
1104  /*
1105  * We disallow indexes on system columns. They would not necessarily get
1106  * updated correctly, and they don't seem useful anyway.
1107  */
1108  for (int i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1109  {
1110  AttrNumber attno = indexInfo->ii_IndexAttrNumbers[i];
1111 
1112  if (attno < 0)
1113  ereport(ERROR,
1114  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1115  errmsg("index creation on system columns is not supported")));
1116  }
1117 
1118  /*
1119  * Also check for system columns used in expressions or predicates.
1120  */
1121  if (indexInfo->ii_Expressions || indexInfo->ii_Predicate)
1122  {
1123  Bitmapset *indexattrs = NULL;
1124 
1125  pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs);
1126  pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs);
1127 
1128  for (int i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
1129  {
1131  indexattrs))
1132  ereport(ERROR,
1133  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1134  errmsg("index creation on system columns is not supported")));
1135  }
1136  }
1137 
1138  /* Is index safe for others to ignore? See set_indexsafe_procflags() */
1139  safe_index = indexInfo->ii_Expressions == NIL &&
1140  indexInfo->ii_Predicate == NIL;
1141 
1142  /*
1143  * Report index creation if appropriate (delay this till after most of the
1144  * error checks)
1145  */
1146  if (stmt->isconstraint && !quiet)
1147  {
1148  const char *constraint_type;
1149 
1150  if (stmt->primary)
1151  constraint_type = "PRIMARY KEY";
1152  else if (stmt->unique)
1153  constraint_type = "UNIQUE";
1154  else if (stmt->excludeOpNames)
1155  constraint_type = "EXCLUDE";
1156  else
1157  {
1158  elog(ERROR, "unknown constraint type");
1159  constraint_type = NULL; /* keep compiler quiet */
1160  }
1161 
1162  ereport(DEBUG1,
1163  (errmsg_internal("%s %s will create implicit index \"%s\" for table \"%s\"",
1164  is_alter_table ? "ALTER TABLE / ADD" : "CREATE TABLE /",
1165  constraint_type,
1166  indexRelationName, RelationGetRelationName(rel))));
1167  }
1168 
1169  /*
1170  * A valid stmt->oldNumber implies that we already have a built form of
1171  * the index. The caller should also decline any index build.
1172  */
1173  Assert(!RelFileNumberIsValid(stmt->oldNumber) || (skip_build && !concurrent));
1174 
1175  /*
1176  * Make the catalog entries for the index, including constraints. This
1177  * step also actually builds the index, except if caller requested not to
1178  * or in concurrent mode, in which case it'll be done later, or doing a
1179  * partitioned index (because those don't have storage).
1180  */
1181  flags = constr_flags = 0;
1182  if (stmt->isconstraint)
1183  flags |= INDEX_CREATE_ADD_CONSTRAINT;
1184  if (skip_build || concurrent || partitioned)
1185  flags |= INDEX_CREATE_SKIP_BUILD;
1186  if (stmt->if_not_exists)
1187  flags |= INDEX_CREATE_IF_NOT_EXISTS;
1188  if (concurrent)
1189  flags |= INDEX_CREATE_CONCURRENT;
1190  if (partitioned)
1191  flags |= INDEX_CREATE_PARTITIONED;
1192  if (stmt->primary)
1193  flags |= INDEX_CREATE_IS_PRIMARY;
1194 
1195  /*
1196  * If the table is partitioned, and recursion was declined but partitions
1197  * exist, mark the index as invalid.
1198  */
1199  if (partitioned && stmt->relation && !stmt->relation->inh)
1200  {
1201  PartitionDesc pd = RelationGetPartitionDesc(rel, true);
1202 
1203  if (pd->nparts != 0)
1204  flags |= INDEX_CREATE_INVALID;
1205  }
1206 
1207  if (stmt->deferrable)
1208  constr_flags |= INDEX_CONSTR_CREATE_DEFERRABLE;
1209  if (stmt->initdeferred)
1210  constr_flags |= INDEX_CONSTR_CREATE_INIT_DEFERRED;
1211  if (stmt->iswithoutoverlaps)
1212  constr_flags |= INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS;
1213 
1214  indexRelationId =
1215  index_create(rel, indexRelationName, indexRelationId, parentIndexId,
1216  parentConstraintId,
1217  stmt->oldNumber, indexInfo, indexColNames,
1218  accessMethodId, tablespaceId,
1219  collationIds, opclassIds, opclassOptions,
1220  coloptions, NULL, reloptions,
1221  flags, constr_flags,
1222  allowSystemTableMods, !check_rights,
1223  &createdConstraintId);
1224 
1225  ObjectAddressSet(address, RelationRelationId, indexRelationId);
1226 
1227  if (!OidIsValid(indexRelationId))
1228  {
1229  /*
1230  * Roll back any GUC changes executed by index functions. Also revert
1231  * to original default_tablespace if we changed it above.
1232  */
1233  AtEOXact_GUC(false, root_save_nestlevel);
1234 
1235  /* Restore userid and security context */
1236  SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
1237 
1238  table_close(rel, NoLock);
1239 
1240  /* If this is the top-level index, we're done */
1241  if (!OidIsValid(parentIndexId))
1243 
1244  return address;
1245  }
1246 
1247  /*
1248  * Roll back any GUC changes executed by index functions, and keep
1249  * subsequent changes local to this command. This is essential if some
1250  * index function changed a behavior-affecting GUC, e.g. search_path.
1251  */
1252  AtEOXact_GUC(false, root_save_nestlevel);
1253  root_save_nestlevel = NewGUCNestLevel();
1255 
1256  /* Add any requested comment */
1257  if (stmt->idxcomment != NULL)
1258  CreateComments(indexRelationId, RelationRelationId, 0,
1259  stmt->idxcomment);
1260 
1261  if (partitioned)
1262  {
1263  PartitionDesc partdesc;
1264 
1265  /*
1266  * Unless caller specified to skip this step (via ONLY), process each
1267  * partition to make sure they all contain a corresponding index.
1268  *
1269  * If we're called internally (no stmt->relation), recurse always.
1270  */
1271  partdesc = RelationGetPartitionDesc(rel, true);
1272  if ((!stmt->relation || stmt->relation->inh) && partdesc->nparts > 0)
1273  {
1274  int nparts = partdesc->nparts;
1275  Oid *part_oids = palloc_array(Oid, nparts);
1276  bool invalidate_parent = false;
1277  Relation parentIndex;
1278  TupleDesc parentDesc;
1279 
1280  /*
1281  * Report the total number of partitions at the start of the
1282  * command; don't update it when being called recursively.
1283  */
1284  if (!OidIsValid(parentIndexId))
1285  {
1286  /*
1287  * When called by ProcessUtilitySlow, the number of partitions
1288  * is passed in as an optimization; but other callers pass -1
1289  * since they don't have the value handy. This should count
1290  * partitions the same way, ie one less than the number of
1291  * relations find_all_inheritors reports.
1292  *
1293  * We assume we needn't ask find_all_inheritors to take locks,
1294  * because that should have happened already for all callers.
1295  * Even if it did not, this is safe as long as we don't try to
1296  * touch the partitions here; the worst consequence would be a
1297  * bogus progress-reporting total.
1298  */
1299  if (total_parts < 0)
1300  {
1301  List *children = find_all_inheritors(tableId, NoLock, NULL);
1302 
1303  total_parts = list_length(children) - 1;
1304  list_free(children);
1305  }
1306 
1308  total_parts);
1309  }
1310 
1311  /* Make a local copy of partdesc->oids[], just for safety */
1312  memcpy(part_oids, partdesc->oids, sizeof(Oid) * nparts);
1313 
1314  /*
1315  * We'll need an IndexInfo describing the parent index. The one
1316  * built above is almost good enough, but not quite, because (for
1317  * example) its predicate expression if any hasn't been through
1318  * expression preprocessing. The most reliable way to get an
1319  * IndexInfo that will match those for child indexes is to build
1320  * it the same way, using BuildIndexInfo().
1321  */
1322  parentIndex = index_open(indexRelationId, lockmode);
1323  indexInfo = BuildIndexInfo(parentIndex);
1324 
1325  parentDesc = RelationGetDescr(rel);
1326 
1327  /*
1328  * For each partition, scan all existing indexes; if one matches
1329  * our index definition and is not already attached to some other
1330  * parent index, attach it to the one we just created.
1331  *
1332  * If none matches, build a new index by calling ourselves
1333  * recursively with the same options (except for the index name).
1334  */
1335  for (int i = 0; i < nparts; i++)
1336  {
1337  Oid childRelid = part_oids[i];
1338  Relation childrel;
1339  Oid child_save_userid;
1340  int child_save_sec_context;
1341  int child_save_nestlevel;
1342  List *childidxs;
1343  ListCell *cell;
1344  AttrMap *attmap;
1345  bool found = false;
1346 
1347  childrel = table_open(childRelid, lockmode);
1348 
1349  GetUserIdAndSecContext(&child_save_userid,
1350  &child_save_sec_context);
1351  SetUserIdAndSecContext(childrel->rd_rel->relowner,
1352  child_save_sec_context | SECURITY_RESTRICTED_OPERATION);
1353  child_save_nestlevel = NewGUCNestLevel();
1355 
1356  /*
1357  * Don't try to create indexes on foreign tables, though. Skip
1358  * those if a regular index, or fail if trying to create a
1359  * constraint index.
1360  */
1361  if (childrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1362  {
1363  if (stmt->unique || stmt->primary)
1364  ereport(ERROR,
1365  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1366  errmsg("cannot create unique index on partitioned table \"%s\"",
1368  errdetail("Table \"%s\" contains partitions that are foreign tables.",
1369  RelationGetRelationName(rel))));
1370 
1371  AtEOXact_GUC(false, child_save_nestlevel);
1372  SetUserIdAndSecContext(child_save_userid,
1373  child_save_sec_context);
1374  table_close(childrel, lockmode);
1375  continue;
1376  }
1377 
1378  childidxs = RelationGetIndexList(childrel);
1379  attmap =
1381  parentDesc,
1382  false);
1383 
1384  foreach(cell, childidxs)
1385  {
1386  Oid cldidxid = lfirst_oid(cell);
1387  Relation cldidx;
1388  IndexInfo *cldIdxInfo;
1389 
1390  /* this index is already partition of another one */
1391  if (has_superclass(cldidxid))
1392  continue;
1393 
1394  cldidx = index_open(cldidxid, lockmode);
1395  cldIdxInfo = BuildIndexInfo(cldidx);
1396  if (CompareIndexInfo(cldIdxInfo, indexInfo,
1397  cldidx->rd_indcollation,
1398  parentIndex->rd_indcollation,
1399  cldidx->rd_opfamily,
1400  parentIndex->rd_opfamily,
1401  attmap))
1402  {
1403  Oid cldConstrOid = InvalidOid;
1404 
1405  /*
1406  * Found a match.
1407  *
1408  * If this index is being created in the parent
1409  * because of a constraint, then the child needs to
1410  * have a constraint also, so look for one. If there
1411  * is no such constraint, this index is no good, so
1412  * keep looking.
1413  */
1414  if (createdConstraintId != InvalidOid)
1415  {
1416  cldConstrOid =
1418  cldidxid);
1419  if (cldConstrOid == InvalidOid)
1420  {
1421  index_close(cldidx, lockmode);
1422  continue;
1423  }
1424  }
1425 
1426  /* Attach index to parent and we're done. */
1427  IndexSetParentIndex(cldidx, indexRelationId);
1428  if (createdConstraintId != InvalidOid)
1429  ConstraintSetParentConstraint(cldConstrOid,
1430  createdConstraintId,
1431  childRelid);
1432 
1433  if (!cldidx->rd_index->indisvalid)
1434  invalidate_parent = true;
1435 
1436  found = true;
1437 
1438  /*
1439  * Report this partition as processed. Note that if
1440  * the partition has children itself, we'd ideally
1441  * count the children and update the progress report
1442  * for all of them; but that seems unduly expensive.
1443  * Instead, the progress report will act like all such
1444  * indirect children were processed in zero time at
1445  * the end of the command.
1446  */
1448 
1449  /* keep lock till commit */
1450  index_close(cldidx, NoLock);
1451  break;
1452  }
1453 
1454  index_close(cldidx, lockmode);
1455  }
1456 
1457  list_free(childidxs);
1458  AtEOXact_GUC(false, child_save_nestlevel);
1459  SetUserIdAndSecContext(child_save_userid,
1460  child_save_sec_context);
1461  table_close(childrel, NoLock);
1462 
1463  /*
1464  * If no matching index was found, create our own.
1465  */
1466  if (!found)
1467  {
1468  IndexStmt *childStmt = copyObject(stmt);
1469  bool found_whole_row;
1470  ListCell *lc;
1471  ObjectAddress childAddr;
1472 
1473  /*
1474  * We can't use the same index name for the child index,
1475  * so clear idxname to let the recursive invocation choose
1476  * a new name. Likewise, the existing target relation
1477  * field is wrong, and if indexOid or oldNumber are set,
1478  * they mustn't be applied to the child either.
1479  */
1480  childStmt->idxname = NULL;
1481  childStmt->relation = NULL;
1482  childStmt->indexOid = InvalidOid;
1483  childStmt->oldNumber = InvalidRelFileNumber;
1486 
1487  /*
1488  * Adjust any Vars (both in expressions and in the index's
1489  * WHERE clause) to match the partition's column numbering
1490  * in case it's different from the parent's.
1491  */
1492  foreach(lc, childStmt->indexParams)
1493  {
1494  IndexElem *ielem = lfirst(lc);
1495 
1496  /*
1497  * If the index parameter is an expression, we must
1498  * translate it to contain child Vars.
1499  */
1500  if (ielem->expr)
1501  {
1502  ielem->expr =
1503  map_variable_attnos((Node *) ielem->expr,
1504  1, 0, attmap,
1505  InvalidOid,
1506  &found_whole_row);
1507  if (found_whole_row)
1508  elog(ERROR, "cannot convert whole-row table reference");
1509  }
1510  }
1511  childStmt->whereClause =
1512  map_variable_attnos(stmt->whereClause, 1, 0,
1513  attmap,
1514  InvalidOid, &found_whole_row);
1515  if (found_whole_row)
1516  elog(ERROR, "cannot convert whole-row table reference");
1517 
1518  /*
1519  * Recurse as the starting user ID. Callee will use that
1520  * for permission checks, then switch again.
1521  */
1522  Assert(GetUserId() == child_save_userid);
1523  SetUserIdAndSecContext(root_save_userid,
1524  root_save_sec_context);
1525  childAddr =
1526  DefineIndex(childRelid, childStmt,
1527  InvalidOid, /* no predefined OID */
1528  indexRelationId, /* this is our child */
1529  createdConstraintId,
1530  -1,
1531  is_alter_table, check_rights,
1532  check_not_in_use,
1533  skip_build, quiet);
1534  SetUserIdAndSecContext(child_save_userid,
1535  child_save_sec_context);
1536 
1537  /*
1538  * Check if the index just created is valid or not, as it
1539  * could be possible that it has been switched as invalid
1540  * when recursing across multiple partition levels.
1541  */
1542  if (!get_index_isvalid(childAddr.objectId))
1543  invalidate_parent = true;
1544  }
1545 
1546  free_attrmap(attmap);
1547  }
1548 
1549  index_close(parentIndex, lockmode);
1550 
1551  /*
1552  * The pg_index row we inserted for this index was marked
1553  * indisvalid=true. But if we attached an existing index that is
1554  * invalid, this is incorrect, so update our row to invalid too.
1555  */
1556  if (invalidate_parent)
1557  {
1558  Relation pg_index = table_open(IndexRelationId, RowExclusiveLock);
1559  HeapTuple tup,
1560  newtup;
1561 
1562  tup = SearchSysCache1(INDEXRELID,
1563  ObjectIdGetDatum(indexRelationId));
1564  if (!HeapTupleIsValid(tup))
1565  elog(ERROR, "cache lookup failed for index %u",
1566  indexRelationId);
1567  newtup = heap_copytuple(tup);
1568  ((Form_pg_index) GETSTRUCT(newtup))->indisvalid = false;
1569  CatalogTupleUpdate(pg_index, &tup->t_self, newtup);
1570  ReleaseSysCache(tup);
1571  table_close(pg_index, RowExclusiveLock);
1572  heap_freetuple(newtup);
1573 
1574  /*
1575  * CCI here to make this update visible, in case this recurses
1576  * across multiple partition levels.
1577  */
1579  }
1580  }
1581 
1582  /*
1583  * Indexes on partitioned tables are not themselves built, so we're
1584  * done here.
1585  */
1586  AtEOXact_GUC(false, root_save_nestlevel);
1587  SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
1588  table_close(rel, NoLock);
1589  if (!OidIsValid(parentIndexId))
1591  else
1592  {
1593  /* Update progress for an intermediate partitioned index itself */
1595  }
1596 
1597  return address;
1598  }
1599 
1600  AtEOXact_GUC(false, root_save_nestlevel);
1601  SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
1602 
1603  if (!concurrent)
1604  {
1605  /* Close the heap and we're done, in the non-concurrent case */
1606  table_close(rel, NoLock);
1607 
1608  /*
1609  * If this is the top-level index, the command is done overall;
1610  * otherwise, increment progress to report one child index is done.
1611  */
1612  if (!OidIsValid(parentIndexId))
1614  else
1616 
1617  return address;
1618  }
1619 
1620  /* save lockrelid and locktag for below, then close rel */
1621  heaprelid = rel->rd_lockInfo.lockRelId;
1622  SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
1623  table_close(rel, NoLock);
1624 
1625  /*
1626  * For a concurrent build, it's important to make the catalog entries
1627  * visible to other transactions before we start to build the index. That
1628  * will prevent them from making incompatible HOT updates. The new index
1629  * will be marked not indisready and not indisvalid, so that no one else
1630  * tries to either insert into it or use it for queries.
1631  *
1632  * We must commit our current transaction so that the index becomes
1633  * visible; then start another. Note that all the data structures we just
1634  * built are lost in the commit. The only data we keep past here are the
1635  * relation IDs.
1636  *
1637  * Before committing, get a session-level lock on the table, to ensure
1638  * that neither it nor the index can be dropped before we finish. This
1639  * cannot block, even if someone else is waiting for access, because we
1640  * already have the same lock within our transaction.
1641  *
1642  * Note: we don't currently bother with a session lock on the index,
1643  * because there are no operations that could change its state while we
1644  * hold lock on the parent table. This might need to change later.
1645  */
1647 
1651 
1652  /* Tell concurrent index builds to ignore us, if index qualifies */
1653  if (safe_index)
1655 
1656  /*
1657  * The index is now visible, so we can report the OID. While on it,
1658  * include the report for the beginning of phase 2.
1659  */
1660  {
1661  const int progress_cols[] = {
1664  };
1665  const int64 progress_vals[] = {
1666  indexRelationId,
1668  };
1669 
1670  pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
1671  }
1672 
1673  /*
1674  * Phase 2 of concurrent index build (see comments for validate_index()
1675  * for an overview of how this works)
1676  *
1677  * Now we must wait until no running transaction could have the table open
1678  * with the old list of indexes. Use ShareLock to consider running
1679  * transactions that hold locks that permit writing to the table. Note we
1680  * do not need to worry about xacts that open the table for writing after
1681  * this point; they will see the new index when they open it.
1682  *
1683  * Note: the reason we use actual lock acquisition here, rather than just
1684  * checking the ProcArray and sleeping, is that deadlock is possible if
1685  * one of the transactions in question is blocked trying to acquire an
1686  * exclusive lock on our table. The lock code will detect deadlock and
1687  * error out properly.
1688  */
1689  WaitForLockers(heaplocktag, ShareLock, true);
1690 
1691  /*
1692  * At this moment we are sure that there are no transactions with the
1693  * table open for write that don't have this new index in their list of
1694  * indexes. We have waited out all the existing transactions and any new
1695  * transaction will have the new index in its list, but the index is still
1696  * marked as "not-ready-for-inserts". The index is consulted while
1697  * deciding HOT-safety though. This arrangement ensures that no new HOT
1698  * chains can be created where the new tuple and the old tuple in the
1699  * chain have different index keys.
1700  *
1701  * We now take a new snapshot, and build the index using all tuples that
1702  * are visible in this snapshot. We can be sure that any HOT updates to
1703  * these tuples will be compatible with the index, since any updates made
1704  * by transactions that didn't know about the index are now committed or
1705  * rolled back. Thus, each visible tuple is either the end of its
1706  * HOT-chain or the extension of the chain is HOT-safe for this index.
1707  */
1708 
1709  /* Set ActiveSnapshot since functions in the indexes may need it */
1711 
1712  /* Perform concurrent build of index */
1713  index_concurrently_build(tableId, indexRelationId);
1714 
1715  /* we can do away with our snapshot */
1717 
1718  /*
1719  * Commit this transaction to make the indisready update visible.
1720  */
1723 
1724  /* Tell concurrent index builds to ignore us, if index qualifies */
1725  if (safe_index)
1727 
1728  /*
1729  * Phase 3 of concurrent index build
1730  *
1731  * We once again wait until no transaction can have the table open with
1732  * the index marked as read-only for updates.
1733  */
1736  WaitForLockers(heaplocktag, ShareLock, true);
1737 
1738  /*
1739  * Now take the "reference snapshot" that will be used by validate_index()
1740  * to filter candidate tuples. Beware! There might still be snapshots in
1741  * use that treat some transaction as in-progress that our reference
1742  * snapshot treats as committed. If such a recently-committed transaction
1743  * deleted tuples in the table, we will not include them in the index; yet
1744  * those transactions which see the deleting one as still-in-progress will
1745  * expect such tuples to be there once we mark the index as valid.
1746  *
1747  * We solve this by waiting for all endangered transactions to exit before
1748  * we mark the index as valid.
1749  *
1750  * We also set ActiveSnapshot to this snap, since functions in indexes may
1751  * need a snapshot.
1752  */
1754  PushActiveSnapshot(snapshot);
1755 
1756  /*
1757  * Scan the index and the heap, insert any missing index entries.
1758  */
1759  validate_index(tableId, indexRelationId, snapshot);
1760 
1761  /*
1762  * Drop the reference snapshot. We must do this before waiting out other
1763  * snapshot holders, else we will deadlock against other processes also
1764  * doing CREATE INDEX CONCURRENTLY, which would see our snapshot as one
1765  * they must wait for. But first, save the snapshot's xmin to use as
1766  * limitXmin for GetCurrentVirtualXIDs().
1767  */
1768  limitXmin = snapshot->xmin;
1769 
1771  UnregisterSnapshot(snapshot);
1772 
1773  /*
1774  * The snapshot subsystem could still contain registered snapshots that
1775  * are holding back our process's advertised xmin; in particular, if
1776  * default_transaction_isolation = serializable, there is a transaction
1777  * snapshot that is still active. The CatalogSnapshot is likewise a
1778  * hazard. To ensure no deadlocks, we must commit and start yet another
1779  * transaction, and do our wait before any snapshot has been taken in it.
1780  */
1783 
1784  /* Tell concurrent index builds to ignore us, if index qualifies */
1785  if (safe_index)
1787 
1788  /* We should now definitely not be advertising any xmin. */
1790 
1791  /*
1792  * The index is now valid in the sense that it contains all currently
1793  * interesting tuples. But since it might not contain tuples deleted just
1794  * before the reference snap was taken, we have to wait out any
1795  * transactions that might have older snapshots.
1796  */
1799  WaitForOlderSnapshots(limitXmin, true);
1800 
1801  /*
1802  * Index can now be marked valid -- update its pg_index entry
1803  */
1805 
1806  /*
1807  * The pg_index update will cause backends (including this one) to update
1808  * relcache entries for the index itself, but we should also send a
1809  * relcache inval on the parent table to force replanning of cached plans.
1810  * Otherwise existing sessions might fail to use the new index where it
1811  * would be useful. (Note that our earlier commits did not create reasons
1812  * to replan; so relcache flush on the index itself was sufficient.)
1813  */
1815 
1816  /*
1817  * Last thing to do is release the session-level lock on the parent table.
1818  */
1820 
1822 
1823  return address;
1824 }
1825 
1826 
1827 /*
1828  * CheckPredicate
1829  * Checks that the given partial-index predicate is valid.
1830  *
1831  * This used to also constrain the form of the predicate to forms that
1832  * indxpath.c could do something with. However, that seems overly
1833  * restrictive. One useful application of partial indexes is to apply
1834  * a UNIQUE constraint across a subset of a table, and in that scenario
1835  * any evaluable predicate will work. So accept any predicate here
1836  * (except ones requiring a plan), and let indxpath.c fend for itself.
1837  */
1838 static void
1840 {
1841  /*
1842  * transformExpr() should have already rejected subqueries, aggregates,
1843  * and window functions, based on the EXPR_KIND_ for a predicate.
1844  */
1845 
1846  /*
1847  * A predicate using mutable functions is probably wrong, for the same
1848  * reasons that we don't allow an index expression to use one.
1849  */
1851  ereport(ERROR,
1852  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1853  errmsg("functions in index predicate must be marked IMMUTABLE")));
1854 }
1855 
1856 /*
1857  * Compute per-index-column information, including indexed column numbers
1858  * or index expressions, opclasses and their options. Note, all output vectors
1859  * should be allocated for all columns, including "including" ones.
1860  *
1861  * If the caller switched to the table owner, ddl_userid is the role for ACL
1862  * checks reached without traversing opaque expressions. Otherwise, it's
1863  * InvalidOid, and other ddl_* arguments are undefined.
1864  */
1865 static void
1867  Oid *typeOids,
1868  Oid *collationOids,
1869  Oid *opclassOids,
1870  Datum *opclassOptions,
1871  int16 *colOptions,
1872  const List *attList, /* list of IndexElem's */
1873  const List *exclusionOpNames,
1874  Oid relId,
1875  const char *accessMethodName,
1876  Oid accessMethodId,
1877  bool amcanorder,
1878  bool isconstraint,
1879  bool iswithoutoverlaps,
1880  Oid ddl_userid,
1881  int ddl_sec_context,
1882  int *ddl_save_nestlevel)
1883 {
1884  ListCell *nextExclOp;
1885  ListCell *lc;
1886  int attn;
1887  int nkeycols = indexInfo->ii_NumIndexKeyAttrs;
1888  Oid save_userid;
1889  int save_sec_context;
1890 
1891  /* Allocate space for exclusion operator info, if needed */
1892  if (exclusionOpNames)
1893  {
1894  Assert(list_length(exclusionOpNames) == nkeycols);
1895  indexInfo->ii_ExclusionOps = palloc_array(Oid, nkeycols);
1896  indexInfo->ii_ExclusionProcs = palloc_array(Oid, nkeycols);
1897  indexInfo->ii_ExclusionStrats = palloc_array(uint16, nkeycols);
1898  nextExclOp = list_head(exclusionOpNames);
1899  }
1900  else
1901  nextExclOp = NULL;
1902 
1903  /*
1904  * If this is a WITHOUT OVERLAPS constraint, we need space for exclusion
1905  * ops, but we don't need to parse anything, so we can let nextExclOp be
1906  * NULL. Note that for partitions/inheriting/LIKE, exclusionOpNames will
1907  * be set, so we already allocated above.
1908  */
1909  if (iswithoutoverlaps)
1910  {
1911  if (exclusionOpNames == NIL)
1912  {
1913  indexInfo->ii_ExclusionOps = palloc_array(Oid, nkeycols);
1914  indexInfo->ii_ExclusionProcs = palloc_array(Oid, nkeycols);
1915  indexInfo->ii_ExclusionStrats = palloc_array(uint16, nkeycols);
1916  }
1917  nextExclOp = NULL;
1918  }
1919 
1920  if (OidIsValid(ddl_userid))
1921  GetUserIdAndSecContext(&save_userid, &save_sec_context);
1922 
1923  /*
1924  * process attributeList
1925  */
1926  attn = 0;
1927  foreach(lc, attList)
1928  {
1929  IndexElem *attribute = (IndexElem *) lfirst(lc);
1930  Oid atttype;
1931  Oid attcollation;
1932 
1933  /*
1934  * Process the column-or-expression to be indexed.
1935  */
1936  if (attribute->name != NULL)
1937  {
1938  /* Simple index attribute */
1939  HeapTuple atttuple;
1940  Form_pg_attribute attform;
1941 
1942  Assert(attribute->expr == NULL);
1943  atttuple = SearchSysCacheAttName(relId, attribute->name);
1944  if (!HeapTupleIsValid(atttuple))
1945  {
1946  /* difference in error message spellings is historical */
1947  if (isconstraint)
1948  ereport(ERROR,
1949  (errcode(ERRCODE_UNDEFINED_COLUMN),
1950  errmsg("column \"%s\" named in key does not exist",
1951  attribute->name)));
1952  else
1953  ereport(ERROR,
1954  (errcode(ERRCODE_UNDEFINED_COLUMN),
1955  errmsg("column \"%s\" does not exist",
1956  attribute->name)));
1957  }
1958  attform = (Form_pg_attribute) GETSTRUCT(atttuple);
1959  indexInfo->ii_IndexAttrNumbers[attn] = attform->attnum;
1960  atttype = attform->atttypid;
1961  attcollation = attform->attcollation;
1962  ReleaseSysCache(atttuple);
1963  }
1964  else
1965  {
1966  /* Index expression */
1967  Node *expr = attribute->expr;
1968 
1969  Assert(expr != NULL);
1970 
1971  if (attn >= nkeycols)
1972  ereport(ERROR,
1973  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1974  errmsg("expressions are not supported in included columns")));
1975  atttype = exprType(expr);
1976  attcollation = exprCollation(expr);
1977 
1978  /*
1979  * Strip any top-level COLLATE clause. This ensures that we treat
1980  * "x COLLATE y" and "(x COLLATE y)" alike.
1981  */
1982  while (IsA(expr, CollateExpr))
1983  expr = (Node *) ((CollateExpr *) expr)->arg;
1984 
1985  if (IsA(expr, Var) &&
1986  ((Var *) expr)->varattno != InvalidAttrNumber)
1987  {
1988  /*
1989  * User wrote "(column)" or "(column COLLATE something)".
1990  * Treat it like simple attribute anyway.
1991  */
1992  indexInfo->ii_IndexAttrNumbers[attn] = ((Var *) expr)->varattno;
1993  }
1994  else
1995  {
1996  indexInfo->ii_IndexAttrNumbers[attn] = 0; /* marks expression */
1997  indexInfo->ii_Expressions = lappend(indexInfo->ii_Expressions,
1998  expr);
1999 
2000  /*
2001  * transformExpr() should have already rejected subqueries,
2002  * aggregates, and window functions, based on the EXPR_KIND_
2003  * for an index expression.
2004  */
2005 
2006  /*
2007  * An expression using mutable functions is probably wrong,
2008  * since if you aren't going to get the same result for the
2009  * same data every time, it's not clear what the index entries
2010  * mean at all.
2011  */
2013  ereport(ERROR,
2014  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2015  errmsg("functions in index expression must be marked IMMUTABLE")));
2016  }
2017  }
2018 
2019  typeOids[attn] = atttype;
2020 
2021  /*
2022  * Included columns have no collation, no opclass and no ordering
2023  * options.
2024  */
2025  if (attn >= nkeycols)
2026  {
2027  if (attribute->collation)
2028  ereport(ERROR,
2029  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2030  errmsg("including column does not support a collation")));
2031  if (attribute->opclass)
2032  ereport(ERROR,
2033  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2034  errmsg("including column does not support an operator class")));
2035  if (attribute->ordering != SORTBY_DEFAULT)
2036  ereport(ERROR,
2037  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2038  errmsg("including column does not support ASC/DESC options")));
2039  if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
2040  ereport(ERROR,
2041  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2042  errmsg("including column does not support NULLS FIRST/LAST options")));
2043 
2044  opclassOids[attn] = InvalidOid;
2045  opclassOptions[attn] = (Datum) 0;
2046  colOptions[attn] = 0;
2047  collationOids[attn] = InvalidOid;
2048  attn++;
2049 
2050  continue;
2051  }
2052 
2053  /*
2054  * Apply collation override if any. Use of ddl_userid is necessary
2055  * due to ACL checks therein, and it's safe because collations don't
2056  * contain opaque expressions (or non-opaque expressions).
2057  */
2058  if (attribute->collation)
2059  {
2060  if (OidIsValid(ddl_userid))
2061  {
2062  AtEOXact_GUC(false, *ddl_save_nestlevel);
2063  SetUserIdAndSecContext(ddl_userid, ddl_sec_context);
2064  }
2065  attcollation = get_collation_oid(attribute->collation, false);
2066  if (OidIsValid(ddl_userid))
2067  {
2068  SetUserIdAndSecContext(save_userid, save_sec_context);
2069  *ddl_save_nestlevel = NewGUCNestLevel();
2071  }
2072  }
2073 
2074  /*
2075  * Check we have a collation iff it's a collatable type. The only
2076  * expected failures here are (1) COLLATE applied to a noncollatable
2077  * type, or (2) index expression had an unresolved collation. But we
2078  * might as well code this to be a complete consistency check.
2079  */
2080  if (type_is_collatable(atttype))
2081  {
2082  if (!OidIsValid(attcollation))
2083  ereport(ERROR,
2084  (errcode(ERRCODE_INDETERMINATE_COLLATION),
2085  errmsg("could not determine which collation to use for index expression"),
2086  errhint("Use the COLLATE clause to set the collation explicitly.")));
2087  }
2088  else
2089  {
2090  if (OidIsValid(attcollation))
2091  ereport(ERROR,
2092  (errcode(ERRCODE_DATATYPE_MISMATCH),
2093  errmsg("collations are not supported by type %s",
2094  format_type_be(atttype))));
2095  }
2096 
2097  collationOids[attn] = attcollation;
2098 
2099  /*
2100  * Identify the opclass to use. Use of ddl_userid is necessary due to
2101  * ACL checks therein. This is safe despite opclasses containing
2102  * opaque expressions (specifically, functions), because only
2103  * superusers can define opclasses.
2104  */
2105  if (OidIsValid(ddl_userid))
2106  {
2107  AtEOXact_GUC(false, *ddl_save_nestlevel);
2108  SetUserIdAndSecContext(ddl_userid, ddl_sec_context);
2109  }
2110  opclassOids[attn] = ResolveOpClass(attribute->opclass,
2111  atttype,
2112  accessMethodName,
2113  accessMethodId);
2114  if (OidIsValid(ddl_userid))
2115  {
2116  SetUserIdAndSecContext(save_userid, save_sec_context);
2117  *ddl_save_nestlevel = NewGUCNestLevel();
2119  }
2120 
2121  /*
2122  * Identify the exclusion operator, if any.
2123  */
2124  if (nextExclOp)
2125  {
2126  List *opname = (List *) lfirst(nextExclOp);
2127  Oid opid;
2128  Oid opfamily;
2129  int strat;
2130 
2131  /*
2132  * Find the operator --- it must accept the column datatype
2133  * without runtime coercion (but binary compatibility is OK).
2134  * Operators contain opaque expressions (specifically, functions).
2135  * compatible_oper_opid() boils down to oper() and
2136  * IsBinaryCoercible(). PostgreSQL would have security problems
2137  * elsewhere if oper() started calling opaque expressions.
2138  */
2139  if (OidIsValid(ddl_userid))
2140  {
2141  AtEOXact_GUC(false, *ddl_save_nestlevel);
2142  SetUserIdAndSecContext(ddl_userid, ddl_sec_context);
2143  }
2144  opid = compatible_oper_opid(opname, atttype, atttype, false);
2145  if (OidIsValid(ddl_userid))
2146  {
2147  SetUserIdAndSecContext(save_userid, save_sec_context);
2148  *ddl_save_nestlevel = NewGUCNestLevel();
2150  }
2151 
2152  /*
2153  * Only allow commutative operators to be used in exclusion
2154  * constraints. If X conflicts with Y, but Y does not conflict
2155  * with X, bad things will happen.
2156  */
2157  if (get_commutator(opid) != opid)
2158  ereport(ERROR,
2159  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2160  errmsg("operator %s is not commutative",
2161  format_operator(opid)),
2162  errdetail("Only commutative operators can be used in exclusion constraints.")));
2163 
2164  /*
2165  * Operator must be a member of the right opfamily, too
2166  */
2167  opfamily = get_opclass_family(opclassOids[attn]);
2168  strat = get_op_opfamily_strategy(opid, opfamily);
2169  if (strat == 0)
2170  {
2171  HeapTuple opftuple;
2172  Form_pg_opfamily opfform;
2173 
2174  /*
2175  * attribute->opclass might not explicitly name the opfamily,
2176  * so fetch the name of the selected opfamily for use in the
2177  * error message.
2178  */
2179  opftuple = SearchSysCache1(OPFAMILYOID,
2180  ObjectIdGetDatum(opfamily));
2181  if (!HeapTupleIsValid(opftuple))
2182  elog(ERROR, "cache lookup failed for opfamily %u",
2183  opfamily);
2184  opfform = (Form_pg_opfamily) GETSTRUCT(opftuple);
2185 
2186  ereport(ERROR,
2187  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2188  errmsg("operator %s is not a member of operator family \"%s\"",
2189  format_operator(opid),
2190  NameStr(opfform->opfname)),
2191  errdetail("The exclusion operator must be related to the index operator class for the constraint.")));
2192  }
2193 
2194  indexInfo->ii_ExclusionOps[attn] = opid;
2195  indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
2196  indexInfo->ii_ExclusionStrats[attn] = strat;
2197  nextExclOp = lnext(exclusionOpNames, nextExclOp);
2198  }
2199  else if (iswithoutoverlaps)
2200  {
2201  StrategyNumber strat;
2202  Oid opid;
2203 
2204  if (attn == nkeycols - 1)
2205  strat = RTOverlapStrategyNumber;
2206  else
2207  strat = RTEqualStrategyNumber;
2208  GetOperatorFromWellKnownStrategy(opclassOids[attn], InvalidOid,
2209  &opid, &strat);
2210  indexInfo->ii_ExclusionOps[attn] = opid;
2211  indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
2212  indexInfo->ii_ExclusionStrats[attn] = strat;
2213  }
2214 
2215  /*
2216  * Set up the per-column options (indoption field). For now, this is
2217  * zero for any un-ordered index, while ordered indexes have DESC and
2218  * NULLS FIRST/LAST options.
2219  */
2220  colOptions[attn] = 0;
2221  if (amcanorder)
2222  {
2223  /* default ordering is ASC */
2224  if (attribute->ordering == SORTBY_DESC)
2225  colOptions[attn] |= INDOPTION_DESC;
2226  /* default null ordering is LAST for ASC, FIRST for DESC */
2227  if (attribute->nulls_ordering == SORTBY_NULLS_DEFAULT)
2228  {
2229  if (attribute->ordering == SORTBY_DESC)
2230  colOptions[attn] |= INDOPTION_NULLS_FIRST;
2231  }
2232  else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
2233  colOptions[attn] |= INDOPTION_NULLS_FIRST;
2234  }
2235  else
2236  {
2237  /* index AM does not support ordering */
2238  if (attribute->ordering != SORTBY_DEFAULT)
2239  ereport(ERROR,
2240  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2241  errmsg("access method \"%s\" does not support ASC/DESC options",
2242  accessMethodName)));
2243  if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
2244  ereport(ERROR,
2245  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2246  errmsg("access method \"%s\" does not support NULLS FIRST/LAST options",
2247  accessMethodName)));
2248  }
2249 
2250  /* Set up the per-column opclass options (attoptions field). */
2251  if (attribute->opclassopts)
2252  {
2253  Assert(attn < nkeycols);
2254 
2255  opclassOptions[attn] =
2256  transformRelOptions((Datum) 0, attribute->opclassopts,
2257  NULL, NULL, false, false);
2258  }
2259  else
2260  opclassOptions[attn] = (Datum) 0;
2261 
2262  attn++;
2263  }
2264 }
2265 
2266 /*
2267  * Resolve possibly-defaulted operator class specification
2268  *
2269  * Note: This is used to resolve operator class specifications in index and
2270  * partition key definitions.
2271  */
2272 Oid
2273 ResolveOpClass(const List *opclass, Oid attrType,
2274  const char *accessMethodName, Oid accessMethodId)
2275 {
2276  char *schemaname;
2277  char *opcname;
2278  HeapTuple tuple;
2279  Form_pg_opclass opform;
2280  Oid opClassId,
2281  opInputType;
2282 
2283  if (opclass == NIL)
2284  {
2285  /* no operator class specified, so find the default */
2286  opClassId = GetDefaultOpClass(attrType, accessMethodId);
2287  if (!OidIsValid(opClassId))
2288  ereport(ERROR,
2289  (errcode(ERRCODE_UNDEFINED_OBJECT),
2290  errmsg("data type %s has no default operator class for access method \"%s\"",
2291  format_type_be(attrType), accessMethodName),
2292  errhint("You must specify an operator class for the index or define a default operator class for the data type.")));
2293  return opClassId;
2294  }
2295 
2296  /*
2297  * Specific opclass name given, so look up the opclass.
2298  */
2299 
2300  /* deconstruct the name list */
2301  DeconstructQualifiedName(opclass, &schemaname, &opcname);
2302 
2303  if (schemaname)
2304  {
2305  /* Look in specific schema only */
2306  Oid namespaceId;
2307 
2308  namespaceId = LookupExplicitNamespace(schemaname, false);
2309  tuple = SearchSysCache3(CLAAMNAMENSP,
2310  ObjectIdGetDatum(accessMethodId),
2311  PointerGetDatum(opcname),
2312  ObjectIdGetDatum(namespaceId));
2313  }
2314  else
2315  {
2316  /* Unqualified opclass name, so search the search path */
2317  opClassId = OpclassnameGetOpcid(accessMethodId, opcname);
2318  if (!OidIsValid(opClassId))
2319  ereport(ERROR,
2320  (errcode(ERRCODE_UNDEFINED_OBJECT),
2321  errmsg("operator class \"%s\" does not exist for access method \"%s\"",
2322  opcname, accessMethodName)));
2323  tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opClassId));
2324  }
2325 
2326  if (!HeapTupleIsValid(tuple))
2327  ereport(ERROR,
2328  (errcode(ERRCODE_UNDEFINED_OBJECT),
2329  errmsg("operator class \"%s\" does not exist for access method \"%s\"",
2330  NameListToString(opclass), accessMethodName)));
2331 
2332  /*
2333  * Verify that the index operator class accepts this datatype. Note we
2334  * will accept binary compatibility.
2335  */
2336  opform = (Form_pg_opclass) GETSTRUCT(tuple);
2337  opClassId = opform->oid;
2338  opInputType = opform->opcintype;
2339 
2340  if (!IsBinaryCoercible(attrType, opInputType))
2341  ereport(ERROR,
2342  (errcode(ERRCODE_DATATYPE_MISMATCH),
2343  errmsg("operator class \"%s\" does not accept data type %s",
2344  NameListToString(opclass), format_type_be(attrType))));
2345 
2346  ReleaseSysCache(tuple);
2347 
2348  return opClassId;
2349 }
2350 
2351 /*
2352  * GetDefaultOpClass
2353  *
2354  * Given the OIDs of a datatype and an access method, find the default
2355  * operator class, if any. Returns InvalidOid if there is none.
2356  */
2357 Oid
2358 GetDefaultOpClass(Oid type_id, Oid am_id)
2359 {
2360  Oid result = InvalidOid;
2361  int nexact = 0;
2362  int ncompatible = 0;
2363  int ncompatiblepreferred = 0;
2364  Relation rel;
2365  ScanKeyData skey[1];
2366  SysScanDesc scan;
2367  HeapTuple tup;
2368  TYPCATEGORY tcategory;
2369 
2370  /* If it's a domain, look at the base type instead */
2371  type_id = getBaseType(type_id);
2372 
2373  tcategory = TypeCategory(type_id);
2374 
2375  /*
2376  * We scan through all the opclasses available for the access method,
2377  * looking for one that is marked default and matches the target type
2378  * (either exactly or binary-compatibly, but prefer an exact match).
2379  *
2380  * We could find more than one binary-compatible match. If just one is
2381  * for a preferred type, use that one; otherwise we fail, forcing the user
2382  * to specify which one he wants. (The preferred-type special case is a
2383  * kluge for varchar: it's binary-compatible to both text and bpchar, so
2384  * we need a tiebreaker.) If we find more than one exact match, then
2385  * someone put bogus entries in pg_opclass.
2386  */
2387  rel = table_open(OperatorClassRelationId, AccessShareLock);
2388 
2389  ScanKeyInit(&skey[0],
2390  Anum_pg_opclass_opcmethod,
2391  BTEqualStrategyNumber, F_OIDEQ,
2392  ObjectIdGetDatum(am_id));
2393 
2394  scan = systable_beginscan(rel, OpclassAmNameNspIndexId, true,
2395  NULL, 1, skey);
2396 
2397  while (HeapTupleIsValid(tup = systable_getnext(scan)))
2398  {
2399  Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
2400 
2401  /* ignore altogether if not a default opclass */
2402  if (!opclass->opcdefault)
2403  continue;
2404  if (opclass->opcintype == type_id)
2405  {
2406  nexact++;
2407  result = opclass->oid;
2408  }
2409  else if (nexact == 0 &&
2410  IsBinaryCoercible(type_id, opclass->opcintype))
2411  {
2412  if (IsPreferredType(tcategory, opclass->opcintype))
2413  {
2414  ncompatiblepreferred++;
2415  result = opclass->oid;
2416  }
2417  else if (ncompatiblepreferred == 0)
2418  {
2419  ncompatible++;
2420  result = opclass->oid;
2421  }
2422  }
2423  }
2424 
2425  systable_endscan(scan);
2426 
2428 
2429  /* raise error if pg_opclass contains inconsistent data */
2430  if (nexact > 1)
2431  ereport(ERROR,
2433  errmsg("there are multiple default operator classes for data type %s",
2434  format_type_be(type_id))));
2435 
2436  if (nexact == 1 ||
2437  ncompatiblepreferred == 1 ||
2438  (ncompatiblepreferred == 0 && ncompatible == 1))
2439  return result;
2440 
2441  return InvalidOid;
2442 }
2443 
2444 /*
2445  * GetOperatorFromWellKnownStrategy
2446  *
2447  * opclass - the opclass to use
2448  * rhstype - the type for the right-hand side, or InvalidOid to use the type of the given opclass.
2449  * opid - holds the operator we found
2450  * strat - holds the input and output strategy number
2451  *
2452  * Finds an operator from a "well-known" strategy number. This is used for
2453  * temporal index constraints (and other temporal features) to look up
2454  * equality and overlaps operators, since the strategy numbers for non-btree
2455  * indexams need not follow any fixed scheme. We ask an opclass support
2456  * function to translate from the well-known number to the internal value. If
2457  * the function isn't defined or it gives no result, we return
2458  * InvalidStrategy.
2459  */
2460 void
2462  Oid *opid, StrategyNumber *strat)
2463 {
2464  Oid opfamily;
2465  Oid opcintype;
2466  StrategyNumber instrat = *strat;
2467 
2468  Assert(instrat == RTEqualStrategyNumber || instrat == RTOverlapStrategyNumber || instrat == RTContainedByStrategyNumber);
2469 
2470  *opid = InvalidOid;
2471 
2472  if (get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
2473  {
2474  /*
2475  * Ask the opclass to translate to its internal stratnum
2476  *
2477  * For now we only need GiST support, but this could support other
2478  * indexams if we wanted.
2479  */
2480  *strat = GistTranslateStratnum(opclass, instrat);
2481  if (*strat == InvalidStrategy)
2482  {
2483  HeapTuple tuple;
2484 
2485  tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
2486  if (!HeapTupleIsValid(tuple))
2487  elog(ERROR, "cache lookup failed for operator class %u", opclass);
2488 
2489  ereport(ERROR,
2490  errcode(ERRCODE_UNDEFINED_OBJECT),
2491  instrat == RTEqualStrategyNumber ? errmsg("could not identify an equality operator for type %s", format_type_be(opcintype)) :
2492  instrat == RTOverlapStrategyNumber ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) :
2493  instrat == RTContainedByStrategyNumber ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0,
2494  errdetail("Could not translate strategy number %d for operator class \"%s\" for access method \"%s\".",
2495  instrat, NameStr(((Form_pg_opclass) GETSTRUCT(tuple))->opcname), "gist"));
2496  }
2497 
2498  /*
2499  * We parameterize rhstype so foreign keys can ask for a <@ operator
2500  * whose rhs matches the aggregate function. For example range_agg
2501  * returns anymultirange.
2502  */
2503  if (!OidIsValid(rhstype))
2504  rhstype = opcintype;
2505  *opid = get_opfamily_member(opfamily, opcintype, rhstype, *strat);
2506  }
2507 
2508  if (!OidIsValid(*opid))
2509  {
2510  HeapTuple tuple;
2511 
2512  tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamily));
2513  if (!HeapTupleIsValid(tuple))
2514  elog(ERROR, "cache lookup failed for operator family %u", opfamily);
2515 
2516  ereport(ERROR,
2517  errcode(ERRCODE_UNDEFINED_OBJECT),
2518  instrat == RTEqualStrategyNumber ? errmsg("could not identify an equality operator for type %s", format_type_be(opcintype)) :
2519  instrat == RTOverlapStrategyNumber ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) :
2520  instrat == RTContainedByStrategyNumber ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0,
2521  errdetail("There is no suitable operator in operator family \"%s\" for access method \"%s\".",
2522  NameStr(((Form_pg_opfamily) GETSTRUCT(tuple))->opfname), "gist"));
2523  }
2524 }
2525 
2526 /*
2527  * makeObjectName()
2528  *
2529  * Create a name for an implicitly created index, sequence, constraint,
2530  * extended statistics, etc.
2531  *
2532  * The parameters are typically: the original table name, the original field
2533  * name, and a "type" string (such as "seq" or "pkey"). The field name
2534  * and/or type can be NULL if not relevant.
2535  *
2536  * The result is a palloc'd string.
2537  *
2538  * The basic result we want is "name1_name2_label", omitting "_name2" or
2539  * "_label" when those parameters are NULL. However, we must generate
2540  * a name with less than NAMEDATALEN characters! So, we truncate one or
2541  * both names if necessary to make a short-enough string. The label part
2542  * is never truncated (so it had better be reasonably short).
2543  *
2544  * The caller is responsible for checking uniqueness of the generated
2545  * name and retrying as needed; retrying will be done by altering the
2546  * "label" string (which is why we never truncate that part).
2547  */
2548 char *
2549 makeObjectName(const char *name1, const char *name2, const char *label)
2550 {
2551  char *name;
2552  int overhead = 0; /* chars needed for label and underscores */
2553  int availchars; /* chars available for name(s) */
2554  int name1chars; /* chars allocated to name1 */
2555  int name2chars; /* chars allocated to name2 */
2556  int ndx;
2557 
2558  name1chars = strlen(name1);
2559  if (name2)
2560  {
2561  name2chars = strlen(name2);
2562  overhead++; /* allow for separating underscore */
2563  }
2564  else
2565  name2chars = 0;
2566  if (label)
2567  overhead += strlen(label) + 1;
2568 
2569  availchars = NAMEDATALEN - 1 - overhead;
2570  Assert(availchars > 0); /* else caller chose a bad label */
2571 
2572  /*
2573  * If we must truncate, preferentially truncate the longer name. This
2574  * logic could be expressed without a loop, but it's simple and obvious as
2575  * a loop.
2576  */
2577  while (name1chars + name2chars > availchars)
2578  {
2579  if (name1chars > name2chars)
2580  name1chars--;
2581  else
2582  name2chars--;
2583  }
2584 
2585  name1chars = pg_mbcliplen(name1, name1chars, name1chars);
2586  if (name2)
2587  name2chars = pg_mbcliplen(name2, name2chars, name2chars);
2588 
2589  /* Now construct the string using the chosen lengths */
2590  name = palloc(name1chars + name2chars + overhead + 1);
2591  memcpy(name, name1, name1chars);
2592  ndx = name1chars;
2593  if (name2)
2594  {
2595  name[ndx++] = '_';
2596  memcpy(name + ndx, name2, name2chars);
2597  ndx += name2chars;
2598  }
2599  if (label)
2600  {
2601  name[ndx++] = '_';
2602  strcpy(name + ndx, label);
2603  }
2604  else
2605  name[ndx] = '\0';
2606 
2607  return name;
2608 }
2609 
2610 /*
2611  * Select a nonconflicting name for a new relation. This is ordinarily
2612  * used to choose index names (which is why it's here) but it can also
2613  * be used for sequences, or any autogenerated relation kind.
2614  *
2615  * name1, name2, and label are used the same way as for makeObjectName(),
2616  * except that the label can't be NULL; digits will be appended to the label
2617  * if needed to create a name that is unique within the specified namespace.
2618  *
2619  * If isconstraint is true, we also avoid choosing a name matching any
2620  * existing constraint in the same namespace. (This is stricter than what
2621  * Postgres itself requires, but the SQL standard says that constraint names
2622  * should be unique within schemas, so we follow that for autogenerated
2623  * constraint names.)
2624  *
2625  * Note: it is theoretically possible to get a collision anyway, if someone
2626  * else chooses the same name concurrently. This is fairly unlikely to be
2627  * a problem in practice, especially if one is holding an exclusive lock on
2628  * the relation identified by name1. However, if choosing multiple names
2629  * within a single command, you'd better create the new object and do
2630  * CommandCounterIncrement before choosing the next one!
2631  *
2632  * Returns a palloc'd string.
2633  */
2634 char *
2635 ChooseRelationName(const char *name1, const char *name2,
2636  const char *label, Oid namespaceid,
2637  bool isconstraint)
2638 {
2639  int pass = 0;
2640  char *relname = NULL;
2641  char modlabel[NAMEDATALEN];
2642 
2643  /* try the unmodified label first */
2644  strlcpy(modlabel, label, sizeof(modlabel));
2645 
2646  for (;;)
2647  {
2648  relname = makeObjectName(name1, name2, modlabel);
2649 
2650  if (!OidIsValid(get_relname_relid(relname, namespaceid)))
2651  {
2652  if (!isconstraint ||
2653  !ConstraintNameExists(relname, namespaceid))
2654  break;
2655  }
2656 
2657  /* found a conflict, so try a new name component */
2658  pfree(relname);
2659  snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
2660  }
2661 
2662  return relname;
2663 }
2664 
2665 /*
2666  * Select the name to be used for an index.
2667  *
2668  * The argument list is pretty ad-hoc :-(
2669  */
2670 static char *
2671 ChooseIndexName(const char *tabname, Oid namespaceId,
2672  const List *colnames, const List *exclusionOpNames,
2673  bool primary, bool isconstraint)
2674 {
2675  char *indexname;
2676 
2677  if (primary)
2678  {
2679  /* the primary key's name does not depend on the specific column(s) */
2680  indexname = ChooseRelationName(tabname,
2681  NULL,
2682  "pkey",
2683  namespaceId,
2684  true);
2685  }
2686  else if (exclusionOpNames != NIL)
2687  {
2688  indexname = ChooseRelationName(tabname,
2689  ChooseIndexNameAddition(colnames),
2690  "excl",
2691  namespaceId,
2692  true);
2693  }
2694  else if (isconstraint)
2695  {
2696  indexname = ChooseRelationName(tabname,
2697  ChooseIndexNameAddition(colnames),
2698  "key",
2699  namespaceId,
2700  true);
2701  }
2702  else
2703  {
2704  indexname = ChooseRelationName(tabname,
2705  ChooseIndexNameAddition(colnames),
2706  "idx",
2707  namespaceId,
2708  false);
2709  }
2710 
2711  return indexname;
2712 }
2713 
2714 /*
2715  * Generate "name2" for a new index given the list of column names for it
2716  * (as produced by ChooseIndexColumnNames). This will be passed to
2717  * ChooseRelationName along with the parent table name and a suitable label.
2718  *
2719  * We know that less than NAMEDATALEN characters will actually be used,
2720  * so we can truncate the result once we've generated that many.
2721  *
2722  * XXX See also ChooseForeignKeyConstraintNameAddition and
2723  * ChooseExtendedStatisticNameAddition.
2724  */
2725 static char *
2727 {
2728  char buf[NAMEDATALEN * 2];
2729  int buflen = 0;
2730  ListCell *lc;
2731 
2732  buf[0] = '\0';
2733  foreach(lc, colnames)
2734  {
2735  const char *name = (const char *) lfirst(lc);
2736 
2737  if (buflen > 0)
2738  buf[buflen++] = '_'; /* insert _ between names */
2739 
2740  /*
2741  * At this point we have buflen <= NAMEDATALEN. name should be less
2742  * than NAMEDATALEN already, but use strlcpy for paranoia.
2743  */
2744  strlcpy(buf + buflen, name, NAMEDATALEN);
2745  buflen += strlen(buf + buflen);
2746  if (buflen >= NAMEDATALEN)
2747  break;
2748  }
2749  return pstrdup(buf);
2750 }
2751 
2752 /*
2753  * Select the actual names to be used for the columns of an index, given the
2754  * list of IndexElems for the columns. This is mostly about ensuring the
2755  * names are unique so we don't get a conflicting-attribute-names error.
2756  *
2757  * Returns a List of plain strings (char *, not String nodes).
2758  */
2759 static List *
2760 ChooseIndexColumnNames(const List *indexElems)
2761 {
2762  List *result = NIL;
2763  ListCell *lc;
2764 
2765  foreach(lc, indexElems)
2766  {
2767  IndexElem *ielem = (IndexElem *) lfirst(lc);
2768  const char *origname;
2769  const char *curname;
2770  int i;
2771  char buf[NAMEDATALEN];
2772 
2773  /* Get the preliminary name from the IndexElem */
2774  if (ielem->indexcolname)
2775  origname = ielem->indexcolname; /* caller-specified name */
2776  else if (ielem->name)
2777  origname = ielem->name; /* simple column reference */
2778  else
2779  origname = "expr"; /* default name for expression */
2780 
2781  /* If it conflicts with any previous column, tweak it */
2782  curname = origname;
2783  for (i = 1;; i++)
2784  {
2785  ListCell *lc2;
2786  char nbuf[32];
2787  int nlen;
2788 
2789  foreach(lc2, result)
2790  {
2791  if (strcmp(curname, (char *) lfirst(lc2)) == 0)
2792  break;
2793  }
2794  if (lc2 == NULL)
2795  break; /* found nonconflicting name */
2796 
2797  sprintf(nbuf, "%d", i);
2798 
2799  /* Ensure generated names are shorter than NAMEDATALEN */
2800  nlen = pg_mbcliplen(origname, strlen(origname),
2801  NAMEDATALEN - 1 - strlen(nbuf));
2802  memcpy(buf, origname, nlen);
2803  strcpy(buf + nlen, nbuf);
2804  curname = buf;
2805  }
2806 
2807  /* And attach to the result list */
2808  result = lappend(result, pstrdup(curname));
2809  }
2810  return result;
2811 }
2812 
2813 /*
2814  * ExecReindex
2815  *
2816  * Primary entry point for manual REINDEX commands. This is mainly a
2817  * preparation wrapper for the real operations that will happen in
2818  * each subroutine of REINDEX.
2819  */
2820 void
2821 ExecReindex(ParseState *pstate, const ReindexStmt *stmt, bool isTopLevel)
2822 {
2823  ReindexParams params = {0};
2824  ListCell *lc;
2825  bool concurrently = false;
2826  bool verbose = false;
2827  char *tablespacename = NULL;
2828 
2829  /* Parse option list */
2830  foreach(lc, stmt->params)
2831  {
2832  DefElem *opt = (DefElem *) lfirst(lc);
2833 
2834  if (strcmp(opt->defname, "verbose") == 0)
2835  verbose = defGetBoolean(opt);
2836  else if (strcmp(opt->defname, "concurrently") == 0)
2837  concurrently = defGetBoolean(opt);
2838  else if (strcmp(opt->defname, "tablespace") == 0)
2839  tablespacename = defGetString(opt);
2840  else
2841  ereport(ERROR,
2842  (errcode(ERRCODE_SYNTAX_ERROR),
2843  errmsg("unrecognized REINDEX option \"%s\"",
2844  opt->defname),
2845  parser_errposition(pstate, opt->location)));
2846  }
2847 
2848  if (concurrently)
2849  PreventInTransactionBlock(isTopLevel,
2850  "REINDEX CONCURRENTLY");
2851 
2852  params.options =
2853  (verbose ? REINDEXOPT_VERBOSE : 0) |
2854  (concurrently ? REINDEXOPT_CONCURRENTLY : 0);
2855 
2856  /*
2857  * Assign the tablespace OID to move indexes to, with InvalidOid to do
2858  * nothing.
2859  */
2860  if (tablespacename != NULL)
2861  {
2862  params.tablespaceOid = get_tablespace_oid(tablespacename, false);
2863 
2864  /* Check permissions except when moving to database's default */
2865  if (OidIsValid(params.tablespaceOid) &&
2867  {
2868  AclResult aclresult;
2869 
2870  aclresult = object_aclcheck(TableSpaceRelationId, params.tablespaceOid,
2871  GetUserId(), ACL_CREATE);
2872  if (aclresult != ACLCHECK_OK)
2873  aclcheck_error(aclresult, OBJECT_TABLESPACE,
2875  }
2876  }
2877  else
2878  params.tablespaceOid = InvalidOid;
2879 
2880  switch (stmt->kind)
2881  {
2882  case REINDEX_OBJECT_INDEX:
2883  ReindexIndex(stmt, &params, isTopLevel);
2884  break;
2885  case REINDEX_OBJECT_TABLE:
2886  ReindexTable(stmt, &params, isTopLevel);
2887  break;
2888  case REINDEX_OBJECT_SCHEMA:
2889  case REINDEX_OBJECT_SYSTEM:
2891 
2892  /*
2893  * This cannot run inside a user transaction block; if we were
2894  * inside a transaction, then its commit- and
2895  * start-transaction-command calls would not have the intended
2896  * effect!
2897  */
2898  PreventInTransactionBlock(isTopLevel,
2899  (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" :
2900  (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" :
2901  "REINDEX DATABASE");
2902  ReindexMultipleTables(stmt, &params);
2903  break;
2904  default:
2905  elog(ERROR, "unrecognized object type: %d",
2906  (int) stmt->kind);
2907  break;
2908  }
2909 }
2910 
2911 /*
2912  * ReindexIndex
2913  * Recreate a specific index.
2914  */
2915 static void
2916 ReindexIndex(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel)
2917 {
2918  const RangeVar *indexRelation = stmt->relation;
2920  Oid indOid;
2921  char persistence;
2922  char relkind;
2923 
2924  /*
2925  * Find and lock index, and check permissions on table; use callback to
2926  * obtain lock on table first, to avoid deadlock hazard. The lock level
2927  * used here must match the index lock obtained in reindex_index().
2928  *
2929  * If it's a temporary index, we will perform a non-concurrent reindex,
2930  * even if CONCURRENTLY was requested. In that case, reindex_index() will
2931  * upgrade the lock, but that's OK, because other sessions can't hold
2932  * locks on our temporary table.
2933  */
2934  state.params = *params;
2935  state.locked_table_oid = InvalidOid;
2936  indOid = RangeVarGetRelidExtended(indexRelation,
2939  0,
2941  &state);
2942 
2943  /*
2944  * Obtain the current persistence and kind of the existing index. We
2945  * already hold a lock on the index.
2946  */
2947  persistence = get_rel_persistence(indOid);
2948  relkind = get_rel_relkind(indOid);
2949 
2950  if (relkind == RELKIND_PARTITIONED_INDEX)
2951  ReindexPartitions(stmt, indOid, params, isTopLevel);
2952  else if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
2953  persistence != RELPERSISTENCE_TEMP)
2955  else
2956  {
2957  ReindexParams newparams = *params;
2958 
2959  newparams.options |= REINDEXOPT_REPORT_PROGRESS;
2960  reindex_index(stmt, indOid, false, persistence, &newparams);
2961  }
2962 }
2963 
2964 /*
2965  * Check permissions on table before acquiring relation lock; also lock
2966  * the heap before the RangeVarGetRelidExtended takes the index lock, to avoid
2967  * deadlocks.
2968  */
2969 static void
2971  Oid relId, Oid oldRelId, void *arg)
2972 {
2973  char relkind;
2975  LOCKMODE table_lockmode;
2976  Oid table_oid;
2977 
2978  /*
2979  * Lock level here should match table lock in reindex_index() for
2980  * non-concurrent case and table locks used by index_concurrently_*() for
2981  * concurrent case.
2982  */
2983  table_lockmode = (state->params.options & REINDEXOPT_CONCURRENTLY) != 0 ?
2985 
2986  /*
2987  * If we previously locked some other index's heap, and the name we're
2988  * looking up no longer refers to that relation, release the now-useless
2989  * lock.
2990  */
2991  if (relId != oldRelId && OidIsValid(oldRelId))
2992  {
2993  UnlockRelationOid(state->locked_table_oid, table_lockmode);
2994  state->locked_table_oid = InvalidOid;
2995  }
2996 
2997  /* If the relation does not exist, there's nothing more to do. */
2998  if (!OidIsValid(relId))
2999  return;
3000 
3001  /*
3002  * If the relation does exist, check whether it's an index. But note that
3003  * the relation might have been dropped between the time we did the name
3004  * lookup and now. In that case, there's nothing to do.
3005  */
3006  relkind = get_rel_relkind(relId);
3007  if (!relkind)
3008  return;
3009  if (relkind != RELKIND_INDEX &&
3010  relkind != RELKIND_PARTITIONED_INDEX)
3011  ereport(ERROR,
3012  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3013  errmsg("\"%s\" is not an index", relation->relname)));
3014 
3015  /* Check permissions */
3016  table_oid = IndexGetRelation(relId, true);
3017  if (OidIsValid(table_oid))
3018  {
3019  AclResult aclresult;
3020 
3021  aclresult = pg_class_aclcheck(table_oid, GetUserId(), ACL_MAINTAIN);
3022  if (aclresult != ACLCHECK_OK)
3023  aclcheck_error(aclresult, OBJECT_INDEX, relation->relname);
3024  }
3025 
3026  /* Lock heap before index to avoid deadlock. */
3027  if (relId != oldRelId)
3028  {
3029  /*
3030  * If the OID isn't valid, it means the index was concurrently
3031  * dropped, which is not a problem for us; just return normally.
3032  */
3033  if (OidIsValid(table_oid))
3034  {
3035  LockRelationOid(table_oid, table_lockmode);
3036  state->locked_table_oid = table_oid;
3037  }
3038  }
3039 }
3040 
3041 /*
3042  * ReindexTable
3043  * Recreate all indexes of a table (and of its toast table, if any)
3044  */
3045 static Oid
3046 ReindexTable(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel)
3047 {
3048  Oid heapOid;
3049  bool result;
3050  const RangeVar *relation = stmt->relation;
3051 
3052  /*
3053  * The lock level used here should match reindex_relation().
3054  *
3055  * If it's a temporary table, we will perform a non-concurrent reindex,
3056  * even if CONCURRENTLY was requested. In that case, reindex_relation()
3057  * will upgrade the lock, but that's OK, because other sessions can't hold
3058  * locks on our temporary table.
3059  */
3060  heapOid = RangeVarGetRelidExtended(relation,
3063  0,
3065 
3066  if (get_rel_relkind(heapOid) == RELKIND_PARTITIONED_TABLE)
3067  ReindexPartitions(stmt, heapOid, params, isTopLevel);
3068  else if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
3069  get_rel_persistence(heapOid) != RELPERSISTENCE_TEMP)
3070  {
3071  result = ReindexRelationConcurrently(stmt, heapOid, params);
3072 
3073  if (!result)
3074  ereport(NOTICE,
3075  (errmsg("table \"%s\" has no indexes that can be reindexed concurrently",
3076  relation->relname)));
3077  }
3078  else
3079  {
3080  ReindexParams newparams = *params;
3081 
3082  newparams.options |= REINDEXOPT_REPORT_PROGRESS;
3083  result = reindex_relation(stmt, heapOid,
3086  &newparams);
3087  if (!result)
3088  ereport(NOTICE,
3089  (errmsg("table \"%s\" has no indexes to reindex",
3090  relation->relname)));
3091  }
3092 
3093  return heapOid;
3094 }
3095 
3096 /*
3097  * ReindexMultipleTables
3098  * Recreate indexes of tables selected by objectName/objectKind.
3099  *
3100  * To reduce the probability of deadlocks, each table is reindexed in a
3101  * separate transaction, so we can release the lock on it right away.
3102  * That means this must not be called within a user transaction block!
3103  */
3104 static void
3106 {
3107 
3108  Oid objectOid;
3109  Relation relationRelation;
3110  TableScanDesc scan;
3111  ScanKeyData scan_keys[1];
3112  HeapTuple tuple;
3113  MemoryContext private_context;
3114  MemoryContext old;
3115  List *relids = NIL;
3116  int num_keys;
3117  bool concurrent_warning = false;
3118  bool tablespace_warning = false;
3119  const char *objectName = stmt->name;
3120  const ReindexObjectType objectKind = stmt->kind;
3121 
3122  Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
3123  objectKind == REINDEX_OBJECT_SYSTEM ||
3124  objectKind == REINDEX_OBJECT_DATABASE);
3125 
3126  /*
3127  * This matches the options enforced by the grammar, where the object name
3128  * is optional for DATABASE and SYSTEM.
3129  */
3130  Assert(objectName || objectKind != REINDEX_OBJECT_SCHEMA);
3131 
3132  if (objectKind == REINDEX_OBJECT_SYSTEM &&
3134  ereport(ERROR,
3135  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3136  errmsg("cannot reindex system catalogs concurrently")));
3137 
3138  /*
3139  * Get OID of object to reindex, being the database currently being used
3140  * by session for a database or for system catalogs, or the schema defined
3141  * by caller. At the same time do permission checks that need different
3142  * processing depending on the object type.
3143  */
3144  if (objectKind == REINDEX_OBJECT_SCHEMA)
3145  {
3146  objectOid = get_namespace_oid(objectName, false);
3147 
3148  if (!object_ownercheck(NamespaceRelationId, objectOid, GetUserId()) &&
3149  !has_privs_of_role(GetUserId(), ROLE_PG_MAINTAIN))
3151  objectName);
3152  }
3153  else
3154  {
3155  objectOid = MyDatabaseId;
3156 
3157  if (objectName && strcmp(objectName, get_database_name(objectOid)) != 0)
3158  ereport(ERROR,
3159  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3160  errmsg("can only reindex the currently open database")));
3161  if (!object_ownercheck(DatabaseRelationId, objectOid, GetUserId()) &&
3162  !has_privs_of_role(GetUserId(), ROLE_PG_MAINTAIN))
3164  get_database_name(objectOid));
3165  }
3166 
3167  /*
3168  * Create a memory context that will survive forced transaction commits we
3169  * do below. Since it is a child of PortalContext, it will go away
3170  * eventually even if we suffer an error; there's no need for special
3171  * abort cleanup logic.
3172  */
3173  private_context = AllocSetContextCreate(PortalContext,
3174  "ReindexMultipleTables",
3176 
3177  /*
3178  * Define the search keys to find the objects to reindex. For a schema, we
3179  * select target relations using relnamespace, something not necessary for
3180  * a database-wide operation.
3181  */
3182  if (objectKind == REINDEX_OBJECT_SCHEMA)
3183  {
3184  num_keys = 1;
3185  ScanKeyInit(&scan_keys[0],
3186  Anum_pg_class_relnamespace,
3187  BTEqualStrategyNumber, F_OIDEQ,
3188  ObjectIdGetDatum(objectOid));
3189  }
3190  else
3191  num_keys = 0;
3192 
3193  /*
3194  * Scan pg_class to build a list of the relations we need to reindex.
3195  *
3196  * We only consider plain relations and materialized views here (toast
3197  * rels will be processed indirectly by reindex_relation).
3198  */
3199  relationRelation = table_open(RelationRelationId, AccessShareLock);
3200  scan = table_beginscan_catalog(relationRelation, num_keys, scan_keys);
3201  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
3202  {
3203  Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
3204  Oid relid = classtuple->oid;
3205 
3206  /*
3207  * Only regular tables and matviews can have indexes, so ignore any
3208  * other kind of relation.
3209  *
3210  * Partitioned tables/indexes are skipped but matching leaf partitions
3211  * are processed.
3212  */
3213  if (classtuple->relkind != RELKIND_RELATION &&
3214  classtuple->relkind != RELKIND_MATVIEW)
3215  continue;
3216 
3217  /* Skip temp tables of other backends; we can't reindex them at all */
3218  if (classtuple->relpersistence == RELPERSISTENCE_TEMP &&
3219  !isTempNamespace(classtuple->relnamespace))
3220  continue;
3221 
3222  /*
3223  * Check user/system classification. SYSTEM processes all the
3224  * catalogs, and DATABASE processes everything that's not a catalog.
3225  */
3226  if (objectKind == REINDEX_OBJECT_SYSTEM &&
3227  !IsCatalogRelationOid(relid))
3228  continue;
3229  else if (objectKind == REINDEX_OBJECT_DATABASE &&
3230  IsCatalogRelationOid(relid))
3231  continue;
3232 
3233  /*
3234  * We already checked privileges on the database or schema, but we
3235  * further restrict reindexing shared catalogs to roles with the
3236  * MAINTAIN privilege on the relation.
3237  */
3238  if (classtuple->relisshared &&
3240  continue;
3241 
3242  /*
3243  * Skip system tables, since index_create() would reject indexing them
3244  * concurrently (and it would likely fail if we tried).
3245  */
3246  if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
3247  IsCatalogRelationOid(relid))
3248  {
3249  if (!concurrent_warning)
3250  ereport(WARNING,
3251  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3252  errmsg("cannot reindex system catalogs concurrently, skipping all")));
3253  concurrent_warning = true;
3254  continue;
3255  }
3256 
3257  /*
3258  * If a new tablespace is set, check if this relation has to be
3259  * skipped.
3260  */
3262  {
3263  bool skip_rel = false;
3264 
3265  /*
3266  * Mapped relations cannot be moved to different tablespaces (in
3267  * particular this eliminates all shared catalogs.).
3268  */
3269  if (RELKIND_HAS_STORAGE(classtuple->relkind) &&
3270  !RelFileNumberIsValid(classtuple->relfilenode))
3271  skip_rel = true;
3272 
3273  /*
3274  * A system relation is always skipped, even with
3275  * allow_system_table_mods enabled.
3276  */
3277  if (IsSystemClass(relid, classtuple))
3278  skip_rel = true;
3279 
3280  if (skip_rel)
3281  {
3282  if (!tablespace_warning)
3283  ereport(WARNING,
3284  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3285  errmsg("cannot move system relations, skipping all")));
3286  tablespace_warning = true;
3287  continue;
3288  }
3289  }
3290 
3291  /* Save the list of relation OIDs in private context */
3292  old = MemoryContextSwitchTo(private_context);
3293 
3294  /*
3295  * We always want to reindex pg_class first if it's selected to be
3296  * reindexed. This ensures that if there is any corruption in
3297  * pg_class' indexes, they will be fixed before we process any other
3298  * tables. This is critical because reindexing itself will try to
3299  * update pg_class.
3300  */
3301  if (relid == RelationRelationId)
3302  relids = lcons_oid(relid, relids);
3303  else
3304  relids = lappend_oid(relids, relid);
3305 
3306  MemoryContextSwitchTo(old);
3307  }
3308  table_endscan(scan);
3309  table_close(relationRelation, AccessShareLock);
3310 
3311  /*
3312  * Process each relation listed in a separate transaction. Note that this
3313  * commits and then starts a new transaction immediately.
3314  */
3316 
3317  MemoryContextDelete(private_context);
3318 }
3319 
3320 /*
3321  * Error callback specific to ReindexPartitions().
3322  */
3323 static void
3325 {
3326  ReindexErrorInfo *errinfo = (ReindexErrorInfo *) arg;
3327 
3328  Assert(RELKIND_HAS_PARTITIONS(errinfo->relkind));
3329 
3330  if (errinfo->relkind == RELKIND_PARTITIONED_TABLE)
3331  errcontext("while reindexing partitioned table \"%s.%s\"",
3332  errinfo->relnamespace, errinfo->relname);
3333  else if (errinfo->relkind == RELKIND_PARTITIONED_INDEX)
3334  errcontext("while reindexing partitioned index \"%s.%s\"",
3335  errinfo->relnamespace, errinfo->relname);
3336 }
3337 
3338 /*
3339  * ReindexPartitions
3340  *
3341  * Reindex a set of partitions, per the partitioned index or table given
3342  * by the caller.
3343  */
3344 static void
3345 ReindexPartitions(const ReindexStmt *stmt, Oid relid, const ReindexParams *params, bool isTopLevel)
3346 {
3347  List *partitions = NIL;
3348  char relkind = get_rel_relkind(relid);
3349  char *relname = get_rel_name(relid);
3350  char *relnamespace = get_namespace_name(get_rel_namespace(relid));
3351  MemoryContext reindex_context;
3352  List *inhoids;
3353  ListCell *lc;
3354  ErrorContextCallback errcallback;
3355  ReindexErrorInfo errinfo;
3356 
3357  Assert(RELKIND_HAS_PARTITIONS(relkind));
3358 
3359  /*
3360  * Check if this runs in a transaction block, with an error callback to
3361  * provide more context under which a problem happens.
3362  */
3363  errinfo.relname = pstrdup(relname);
3364  errinfo.relnamespace = pstrdup(relnamespace);
3365  errinfo.relkind = relkind;
3366  errcallback.callback = reindex_error_callback;
3367  errcallback.arg = (void *) &errinfo;
3368  errcallback.previous = error_context_stack;
3369  error_context_stack = &errcallback;
3370 
3371  PreventInTransactionBlock(isTopLevel,
3372  relkind == RELKIND_PARTITIONED_TABLE ?
3373  "REINDEX TABLE" : "REINDEX INDEX");
3374 
3375  /* Pop the error context stack */
3376  error_context_stack = errcallback.previous;
3377 
3378  /*
3379  * Create special memory context for cross-transaction storage.
3380  *
3381  * Since it is a child of PortalContext, it will go away eventually even
3382  * if we suffer an error so there is no need for special abort cleanup
3383  * logic.
3384  */
3385  reindex_context = AllocSetContextCreate(PortalContext, "Reindex",
3387 
3388  /* ShareLock is enough to prevent schema modifications */
3389  inhoids = find_all_inheritors(relid, ShareLock, NULL);
3390 
3391  /*
3392  * The list of relations to reindex are the physical partitions of the
3393  * tree so discard any partitioned table or index.
3394  */
3395  foreach(lc, inhoids)
3396  {
3397  Oid partoid = lfirst_oid(lc);
3398  char partkind = get_rel_relkind(partoid);
3399  MemoryContext old_context;
3400 
3401  /*
3402  * This discards partitioned tables, partitioned indexes and foreign
3403  * tables.
3404  */
3405  if (!RELKIND_HAS_STORAGE(partkind))
3406  continue;
3407 
3408  Assert(partkind == RELKIND_INDEX ||
3409  partkind == RELKIND_RELATION);
3410 
3411  /* Save partition OID */
3412  old_context = MemoryContextSwitchTo(reindex_context);
3413  partitions = lappend_oid(partitions, partoid);
3414  MemoryContextSwitchTo(old_context);
3415  }
3416 
3417  /*
3418  * Process each partition listed in a separate transaction. Note that
3419  * this commits and then starts a new transaction immediately.
3420  */
3422 
3423  /*
3424  * Clean up working storage --- note we must do this after
3425  * StartTransactionCommand, else we might be trying to delete the active
3426  * context!
3427  */
3428  MemoryContextDelete(reindex_context);
3429 }
3430 
3431 /*
3432  * ReindexMultipleInternal
3433  *
3434  * Reindex a list of relations, each one being processed in its own
3435  * transaction. This commits the existing transaction immediately,
3436  * and starts a new transaction when finished.
3437  */
3438 static void
3440 {
3441  ListCell *l;
3442 
3445 
3446  foreach(l, relids)
3447  {
3448  Oid relid = lfirst_oid(l);
3449  char relkind;
3450  char relpersistence;
3451 
3453 
3454  /* functions in indexes may want a snapshot set */
3456 
3457  /* check if the relation still exists */
3458  if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
3459  {
3462  continue;
3463  }
3464 
3465  /*
3466  * Check permissions except when moving to database's default if a new
3467  * tablespace is chosen. Note that this check also happens in
3468  * ExecReindex(), but we do an extra check here as this runs across
3469  * multiple transactions.
3470  */
3473  {
3474  AclResult aclresult;
3475 
3476  aclresult = object_aclcheck(TableSpaceRelationId, params->tablespaceOid,
3477  GetUserId(), ACL_CREATE);
3478  if (aclresult != ACLCHECK_OK)
3479  aclcheck_error(aclresult, OBJECT_TABLESPACE,
3481  }
3482 
3483  relkind = get_rel_relkind(relid);
3484  relpersistence = get_rel_persistence(relid);
3485 
3486  /*
3487  * Partitioned tables and indexes can never be processed directly, and
3488  * a list of their leaves should be built first.
3489  */
3490  Assert(!RELKIND_HAS_PARTITIONS(relkind));
3491 
3492  if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
3493  relpersistence != RELPERSISTENCE_TEMP)
3494  {
3495  ReindexParams newparams = *params;
3496 
3497  newparams.options |= REINDEXOPT_MISSING_OK;
3498  (void) ReindexRelationConcurrently(stmt, relid, &newparams);
3499  if (ActiveSnapshotSet())
3501  /* ReindexRelationConcurrently() does the verbose output */
3502  }
3503  else if (relkind == RELKIND_INDEX)
3504  {
3505  ReindexParams newparams = *params;
3506 
3507  newparams.options |=
3509  reindex_index(stmt, relid, false, relpersistence, &newparams);
3511  /* reindex_index() does the verbose output */
3512  }
3513  else
3514  {
3515  bool result;
3516  ReindexParams newparams = *params;
3517 
3518  newparams.options |=
3520  result = reindex_relation(stmt, relid,
3523  &newparams);
3524 
3525  if (result && (params->options & REINDEXOPT_VERBOSE) != 0)
3526  ereport(INFO,
3527  (errmsg("table \"%s.%s\" was reindexed",
3529  get_rel_name(relid))));
3530 
3532  }
3533 
3535  }
3536 
3538 }
3539 
3540 
3541 /*
3542  * ReindexRelationConcurrently - process REINDEX CONCURRENTLY for given
3543  * relation OID
3544  *
3545  * 'relationOid' can either belong to an index, a table or a materialized
3546  * view. For tables and materialized views, all its indexes will be rebuilt,
3547  * excluding invalid indexes and any indexes used in exclusion constraints,
3548  * but including its associated toast table indexes. For indexes, the index
3549  * itself will be rebuilt.
3550  *
3551  * The locks taken on parent tables and involved indexes are kept until the
3552  * transaction is committed, at which point a session lock is taken on each
3553  * relation. Both of these protect against concurrent schema changes.
3554  *
3555  * Returns true if any indexes have been rebuilt (including toast table's
3556  * indexes, when relevant), otherwise returns false.
3557  *
3558  * NOTE: This cannot be used on temporary relations. A concurrent build would
3559  * cause issues with ON COMMIT actions triggered by the transactions of the
3560  * concurrent build. Temporary relations are not subject to concurrent
3561  * concerns, so there's no need for the more complicated concurrent build,
3562  * anyway, and a non-concurrent reindex is more efficient.
3563  */
3564 static bool
3566 {
3567  typedef struct ReindexIndexInfo
3568  {
3569  Oid indexId;
3570  Oid tableId;
3571  Oid amId;
3572  bool safe; /* for set_indexsafe_procflags */
3573  } ReindexIndexInfo;
3574  List *heapRelationIds = NIL;
3575  List *indexIds = NIL;
3576  List *newIndexIds = NIL;
3577  List *relationLocks = NIL;
3578  List *lockTags = NIL;
3579  ListCell *lc,
3580  *lc2;
3581  MemoryContext private_context;
3582  MemoryContext oldcontext;
3583  char relkind;
3584  char *relationName = NULL;
3585  char *relationNamespace = NULL;
3586  PGRUsage ru0;
3587  const int progress_index[] = {
3592  };
3593  int64 progress_vals[4];
3594 
3595  /*
3596  * Create a memory context that will survive forced transaction commits we
3597  * do below. Since it is a child of PortalContext, it will go away
3598  * eventually even if we suffer an error; there's no need for special
3599  * abort cleanup logic.
3600  */
3601  private_context = AllocSetContextCreate(PortalContext,
3602  "ReindexConcurrent",
3604 
3605  if ((params->options & REINDEXOPT_VERBOSE) != 0)
3606  {
3607  /* Save data needed by REINDEX VERBOSE in private context */
3608  oldcontext = MemoryContextSwitchTo(private_context);
3609 
3610  relationName = get_rel_name(relationOid);
3611  relationNamespace = get_namespace_name(get_rel_namespace(relationOid));
3612 
3613  pg_rusage_init(&ru0);
3614 
3615  MemoryContextSwitchTo(oldcontext);
3616  }
3617 
3618  relkind = get_rel_relkind(relationOid);
3619 
3620  /*
3621  * Extract the list of indexes that are going to be rebuilt based on the
3622  * relation Oid given by caller.
3623  */
3624  switch (relkind)
3625  {
3626  case RELKIND_RELATION:
3627  case RELKIND_MATVIEW:
3628  case RELKIND_TOASTVALUE:
3629  {
3630  /*
3631  * In the case of a relation, find all its indexes including
3632  * toast indexes.
3633  */
3634  Relation heapRelation;
3635 
3636  /* Save the list of relation OIDs in private context */
3637  oldcontext = MemoryContextSwitchTo(private_context);
3638 
3639  /* Track this relation for session locks */
3640  heapRelationIds = lappend_oid(heapRelationIds, relationOid);
3641 
3642  MemoryContextSwitchTo(oldcontext);
3643 
3644  if (IsCatalogRelationOid(relationOid))
3645  ereport(ERROR,
3646  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3647  errmsg("cannot reindex system catalogs concurrently")));
3648 
3649  /* Open relation to get its indexes */
3650  if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3651  {
3652  heapRelation = try_table_open(relationOid,
3654  /* leave if relation does not exist */
3655  if (!heapRelation)
3656  break;
3657  }
3658  else
3659  heapRelation = table_open(relationOid,
3661 
3662  if (OidIsValid(params->tablespaceOid) &&
3663  IsSystemRelation(heapRelation))
3664  ereport(ERROR,
3665  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3666  errmsg("cannot move system relation \"%s\"",
3667  RelationGetRelationName(heapRelation))));
3668 
3669  /* Add all the valid indexes of relation to list */
3670  foreach(lc, RelationGetIndexList(heapRelation))
3671  {
3672  Oid cellOid = lfirst_oid(lc);
3673  Relation indexRelation = index_open(cellOid,
3675 
3676  if (!indexRelation->rd_index->indisvalid)
3677  ereport(WARNING,
3678  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3679  errmsg("skipping reindex of invalid index \"%s.%s\"",
3681  get_rel_name(cellOid)),
3682  errhint("Use DROP INDEX or REINDEX INDEX.")));
3683  else if (indexRelation->rd_index->indisexclusion)
3684  ereport(WARNING,
3685  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3686  errmsg("cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping",
3688  get_rel_name(cellOid))));
3689  else
3690  {
3691  ReindexIndexInfo *idx;
3692 
3693  /* Save the list of relation OIDs in private context */
3694  oldcontext = MemoryContextSwitchTo(private_context);
3695 
3696  idx = palloc_object(ReindexIndexInfo);
3697  idx->indexId = cellOid;
3698  /* other fields set later */
3699 
3700  indexIds = lappend(indexIds, idx);
3701 
3702  MemoryContextSwitchTo(oldcontext);
3703  }
3704 
3705  index_close(indexRelation, NoLock);
3706  }
3707 
3708  /* Also add the toast indexes */
3709  if (OidIsValid(heapRelation->rd_rel->reltoastrelid))
3710  {
3711  Oid toastOid = heapRelation->rd_rel->reltoastrelid;
3712  Relation toastRelation = table_open(toastOid,
3714 
3715  /* Save the list of relation OIDs in private context */
3716  oldcontext = MemoryContextSwitchTo(private_context);
3717 
3718  /* Track this relation for session locks */
3719  heapRelationIds = lappend_oid(heapRelationIds, toastOid);
3720 
3721  MemoryContextSwitchTo(oldcontext);
3722 
3723  foreach(lc2, RelationGetIndexList(toastRelation))
3724  {
3725  Oid cellOid = lfirst_oid(lc2);
3726  Relation indexRelation = index_open(cellOid,
3728 
3729  if (!indexRelation->rd_index->indisvalid)
3730  ereport(WARNING,
3731  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3732  errmsg("skipping reindex of invalid index \"%s.%s\"",
3734  get_rel_name(cellOid)),
3735  errhint("Use DROP INDEX or REINDEX INDEX.")));
3736  else
3737  {
3738  ReindexIndexInfo *idx;
3739 
3740  /*
3741  * Save the list of relation OIDs in private
3742  * context
3743  */
3744  oldcontext = MemoryContextSwitchTo(private_context);
3745 
3746  idx = palloc_object(ReindexIndexInfo);
3747  idx->indexId = cellOid;
3748  indexIds = lappend(indexIds, idx);
3749  /* other fields set later */
3750 
3751  MemoryContextSwitchTo(oldcontext);
3752  }
3753 
3754  index_close(indexRelation, NoLock);
3755  }
3756 
3757  table_close(toastRelation, NoLock);
3758  }
3759 
3760  table_close(heapRelation, NoLock);
3761  break;
3762  }
3763  case RELKIND_INDEX:
3764  {
3765  Oid heapId = IndexGetRelation(relationOid,
3766  (params->options & REINDEXOPT_MISSING_OK) != 0);
3767  Relation heapRelation;
3768  ReindexIndexInfo *idx;
3769 
3770  /* if relation is missing, leave */
3771  if (!OidIsValid(heapId))
3772  break;
3773 
3774  if (IsCatalogRelationOid(heapId))
3775  ereport(ERROR,
3776  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3777  errmsg("cannot reindex system catalogs concurrently")));
3778 
3779  /*
3780  * Don't allow reindex for an invalid index on TOAST table, as
3781  * if rebuilt it would not be possible to drop it. Match
3782  * error message in reindex_index().
3783  */
3784  if (IsToastNamespace(get_rel_namespace(relationOid)) &&
3785  !get_index_isvalid(relationOid))
3786  ereport(ERROR,
3787  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3788  errmsg("cannot reindex invalid index on TOAST table")));
3789 
3790  /*
3791  * Check if parent relation can be locked and if it exists,
3792  * this needs to be done at this stage as the list of indexes
3793  * to rebuild is not complete yet, and REINDEXOPT_MISSING_OK
3794  * should not be used once all the session locks are taken.
3795  */
3796  if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3797  {
3798  heapRelation = try_table_open(heapId,
3800  /* leave if relation does not exist */
3801  if (!heapRelation)
3802  break;
3803  }
3804  else
3805  heapRelation = table_open(heapId,
3807 
3808  if (OidIsValid(params->tablespaceOid) &&
3809  IsSystemRelation(heapRelation))
3810  ereport(ERROR,
3811  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3812  errmsg("cannot move system relation \"%s\"",
3813  get_rel_name(relationOid))));
3814 
3815  table_close(heapRelation, NoLock);
3816 
3817  /* Save the list of relation OIDs in private context */
3818  oldcontext = MemoryContextSwitchTo(private_context);
3819 
3820  /* Track the heap relation of this index for session locks */
3821  heapRelationIds = list_make1_oid(heapId);
3822 
3823  /*
3824  * Save the list of relation OIDs in private context. Note
3825  * that invalid indexes are allowed here.
3826  */
3827  idx = palloc_object(ReindexIndexInfo);
3828  idx->indexId = relationOid;
3829  indexIds = lappend(indexIds, idx);
3830  /* other fields set later */
3831 
3832  MemoryContextSwitchTo(oldcontext);
3833  break;
3834  }
3835 
3836  case RELKIND_PARTITIONED_TABLE:
3837  case RELKIND_PARTITIONED_INDEX:
3838  default:
3839  /* Return error if type of relation is not supported */
3840  ereport(ERROR,
3841  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3842  errmsg("cannot reindex this type of relation concurrently")));
3843  break;
3844  }
3845 
3846  /*
3847  * Definitely no indexes, so leave. Any checks based on
3848  * REINDEXOPT_MISSING_OK should be done only while the list of indexes to
3849  * work on is built as the session locks taken before this transaction
3850  * commits will make sure that they cannot be dropped by a concurrent
3851  * session until this operation completes.
3852  */
3853  if (indexIds == NIL)
3854  return false;
3855 
3856  /* It's not a shared catalog, so refuse to move it to shared tablespace */
3857  if (params->tablespaceOid == GLOBALTABLESPACE_OID)
3858  ereport(ERROR,
3859  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3860  errmsg("cannot move non-shared relation to tablespace \"%s\"",
3861  get_tablespace_name(params->tablespaceOid))));
3862 
3863  Assert(heapRelationIds != NIL);
3864 
3865  /*-----
3866  * Now we have all the indexes we want to process in indexIds.
3867  *
3868  * The phases now are:
3869  *
3870  * 1. create new indexes in the catalog
3871  * 2. build new indexes
3872  * 3. let new indexes catch up with tuples inserted in the meantime
3873  * 4. swap index names
3874  * 5. mark old indexes as dead
3875  * 6. drop old indexes
3876  *
3877  * We process each phase for all indexes before moving to the next phase,
3878  * for efficiency.
3879  */
3880 
3881  /*
3882  * Phase 1 of REINDEX CONCURRENTLY
3883  *
3884  * Create a new index with the same properties as the old one, but it is
3885  * only registered in catalogs and will be built later. Then get session
3886  * locks on all involved tables. See analogous code in DefineIndex() for
3887  * more detailed comments.
3888  */
3889 
3890  foreach(lc, indexIds)
3891  {
3892  char *concurrentName;
3893  ReindexIndexInfo *idx = lfirst(lc);
3894  ReindexIndexInfo *newidx;
3895  Oid newIndexId;
3896  Relation indexRel;
3897  Relation heapRel;
3898  Oid save_userid;
3899  int save_sec_context;
3900  int save_nestlevel;
3901  Relation newIndexRel;
3902  LockRelId *lockrelid;
3903  Oid tablespaceid;
3904 
3905  indexRel = index_open(idx->indexId, ShareUpdateExclusiveLock);
3906  heapRel = table_open(indexRel->rd_index->indrelid,
3908 
3909  /*
3910  * Switch to the table owner's userid, so that any index functions are
3911  * run as that user. Also lock down security-restricted operations
3912  * and arrange to make GUC variable changes local to this command.
3913  */
3914  GetUserIdAndSecContext(&save_userid, &save_sec_context);
3915  SetUserIdAndSecContext(heapRel->rd_rel->relowner,
3916  save_sec_context | SECURITY_RESTRICTED_OPERATION);
3917  save_nestlevel = NewGUCNestLevel();
3919 
3920  /* determine safety of this index for set_indexsafe_procflags */
3921  idx->safe = (RelationGetIndexExpressions(indexRel) == NIL &&
3922  RelationGetIndexPredicate(indexRel) == NIL);
3923 
3924 #ifdef USE_INJECTION_POINTS
3925  if (idx->safe)
3926  INJECTION_POINT("reindex-conc-index-safe");
3927  else
3928  INJECTION_POINT("reindex-conc-index-not-safe");
3929 #endif
3930 
3931  idx->tableId = RelationGetRelid(heapRel);
3932  idx->amId = indexRel->rd_rel->relam;
3933 
3934  /* This function shouldn't be called for temporary relations. */
3935  if (indexRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
3936  elog(ERROR, "cannot reindex a temporary table concurrently");
3937 
3939 
3941  progress_vals[1] = 0; /* initializing */
3942  progress_vals[2] = idx->indexId;
3943  progress_vals[3] = idx->amId;
3944  pgstat_progress_update_multi_param(4, progress_index, progress_vals);
3945 
3946  /* Choose a temporary relation name for the new index */
3947  concurrentName = ChooseRelationName(get_rel_name(idx->indexId),
3948  NULL,
3949  "ccnew",
3950  get_rel_namespace(indexRel->rd_index->indrelid),
3951  false);
3952 
3953  /* Choose the new tablespace, indexes of toast tables are not moved */
3954  if (OidIsValid(params->tablespaceOid) &&
3955  heapRel->rd_rel->relkind != RELKIND_TOASTVALUE)
3956  tablespaceid = params->tablespaceOid;
3957  else
3958  tablespaceid = indexRel->rd_rel->reltablespace;
3959 
3960  /* Create new index definition based on given index */
3961  newIndexId = index_concurrently_create_copy(heapRel,
3962  idx->indexId,
3963  tablespaceid,
3964  concurrentName);
3965 
3966  /*
3967  * Now open the relation of the new index, a session-level lock is
3968  * also needed on it.
3969  */
3970  newIndexRel = index_open(newIndexId, ShareUpdateExclusiveLock);
3971 
3972  /*
3973  * Save the list of OIDs and locks in private context
3974  */
3975  oldcontext = MemoryContextSwitchTo(private_context);
3976 
3977  newidx = palloc_object(ReindexIndexInfo);
3978  newidx->indexId = newIndexId;
3979  newidx->safe = idx->safe;
3980  newidx->tableId = idx->tableId;
3981  newidx->amId = idx->amId;
3982 
3983  newIndexIds = lappend(newIndexIds, newidx);
3984 
3985  /*
3986  * Save lockrelid to protect each relation from drop then close
3987  * relations. The lockrelid on parent relation is not taken here to
3988  * avoid multiple locks taken on the same relation, instead we rely on
3989  * parentRelationIds built earlier.
3990  */
3991  lockrelid = palloc_object(LockRelId);
3992  *lockrelid = indexRel->rd_lockInfo.lockRelId;
3993  relationLocks = lappend(relationLocks, lockrelid);
3994  lockrelid = palloc_object(LockRelId);
3995  *lockrelid = newIndexRel->rd_lockInfo.lockRelId;
3996  relationLocks = lappend(relationLocks, lockrelid);
3997 
3998  MemoryContextSwitchTo(oldcontext);
3999 
4000  index_close(indexRel, NoLock);
4001  index_close(newIndexRel, NoLock);
4002 
4003  /* Roll back any GUC changes executed by index functions */
4004  AtEOXact_GUC(false, save_nestlevel);
4005 
4006  /* Restore userid and security context */
4007  SetUserIdAndSecContext(save_userid, save_sec_context);
4008 
4009  table_close(heapRel, NoLock);
4010 
4011  /*
4012  * If a statement is available, telling that this comes from a REINDEX
4013  * command, collect the new index for event triggers.
4014  */
4015  if (stmt)
4016  {
4017  ObjectAddress address;
4018 
4019  ObjectAddressSet(address, RelationRelationId, newIndexId);
4022  (Node *) stmt);
4023  }
4024  }
4025 
4026  /*
4027  * Save the heap lock for following visibility checks with other backends
4028  * might conflict with this session.
4029  */
4030  foreach(lc, heapRelationIds)
4031  {
4033  LockRelId *lockrelid;
4034  LOCKTAG *heaplocktag;
4035 
4036  /* Save the list of locks in private context */
4037  oldcontext = MemoryContextSwitchTo(private_context);
4038 
4039  /* Add lockrelid of heap relation to the list of locked relations */
4040  lockrelid = palloc_object(LockRelId);
4041  *lockrelid = heapRelation->rd_lockInfo.lockRelId;
4042  relationLocks = lappend(relationLocks, lockrelid);
4043 
4044  heaplocktag = palloc_object(LOCKTAG);
4045 
4046  /* Save the LOCKTAG for this parent relation for the wait phase */
4047  SET_LOCKTAG_RELATION(*heaplocktag, lockrelid->dbId, lockrelid->relId);
4048  lockTags = lappend(lockTags, heaplocktag);
4049 
4050  MemoryContextSwitchTo(oldcontext);
4051 
4052  /* Close heap relation */
4053  table_close(heapRelation, NoLock);
4054  }
4055 
4056  /* Get a session-level lock on each table. */
4057  foreach(lc, relationLocks)
4058  {
4059  LockRelId *lockrelid = (LockRelId *) lfirst(lc);
4060 
4062  }
4063 
4067 
4068  /*
4069  * Because we don't take a snapshot in this transaction, there's no need
4070  * to set the PROC_IN_SAFE_IC flag here.
4071  */
4072 
4073  /*
4074  * Phase 2 of REINDEX CONCURRENTLY
4075  *
4076  * Build the new indexes in a separate transaction for each index to avoid
4077  * having open transactions for an unnecessary long time. But before
4078  * doing that, wait until no running transactions could have the table of
4079  * the index open with the old list of indexes. See "phase 2" in
4080  * DefineIndex() for more details.
4081  */
4082 
4085  WaitForLockersMultiple(lockTags, ShareLock, true);
4087 
4088  foreach(lc, newIndexIds)
4089  {
4090  ReindexIndexInfo *newidx = lfirst(lc);
4091 
4092  /* Start new transaction for this index's concurrent build */
4094 
4095  /*
4096  * Check for user-requested abort. This is inside a transaction so as
4097  * xact.c does not issue a useless WARNING, and ensures that
4098  * session-level locks are cleaned up on abort.
4099  */
4101 
4102  /* Tell concurrent indexing to ignore us, if index qualifies */
4103  if (newidx->safe)
4105 
4106  /* Set ActiveSnapshot since functions in the indexes may need it */
4108 
4109  /*
4110  * Update progress for the index to build, with the correct parent
4111  * table involved.
4112  */
4115  progress_vals[1] = PROGRESS_CREATEIDX_PHASE_BUILD;
4116  progress_vals[2] = newidx->indexId;
4117  progress_vals[3] = newidx->amId;
4118  pgstat_progress_update_multi_param(4, progress_index, progress_vals);
4119 
4120  /* Perform concurrent build of new index */
4121  index_concurrently_build(newidx->tableId, newidx->indexId);
4122 
4125  }
4126 
4128 
4129  /*
4130  * Because we don't take a snapshot or Xid in this transaction, there's no
4131  * need to set the PROC_IN_SAFE_IC flag here.
4132  */
4133 
4134  /*
4135  * Phase 3 of REINDEX CONCURRENTLY
4136  *
4137  * During this phase the old indexes catch up with any new tuples that
4138  * were created during the previous phase. See "phase 3" in DefineIndex()
4139  * for more details.
4140  */
4141 
4144  WaitForLockersMultiple(lockTags, ShareLock, true);
4146 
4147  foreach(lc, newIndexIds)
4148  {
4149  ReindexIndexInfo *newidx = lfirst(lc);
4150  TransactionId limitXmin;
4151  Snapshot snapshot;
4152 
4154 
4155  /*
4156  * Check for user-requested abort. This is inside a transaction so as
4157  * xact.c does not issue a useless WARNING, and ensures that
4158  * session-level locks are cleaned up on abort.
4159  */
4161 
4162  /* Tell concurrent indexing to ignore us, if index qualifies */
4163  if (newidx->safe)
4165 
4166  /*
4167  * Take the "reference snapshot" that will be used by validate_index()
4168  * to filter candidate tuples.
4169  */
4171  PushActiveSnapshot(snapshot);
4172 
4173  /*
4174  * Update progress for the index to build, with the correct parent
4175  * table involved.
4176  */
4179  progress_vals[1] = PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN;
4180  progress_vals[2] = newidx->indexId;
4181  progress_vals[3] = newidx->amId;
4182  pgstat_progress_update_multi_param(4, progress_index, progress_vals);
4183 
4184  validate_index(newidx->tableId, newidx->indexId, snapshot);
4185 
4186  /*
4187  * We can now do away with our active snapshot, we still need to save
4188  * the xmin limit to wait for older snapshots.
4189  */
4190  limitXmin = snapshot->xmin;
4191 
4193  UnregisterSnapshot(snapshot);
4194 
4195  /*
4196  * To ensure no deadlocks, we must commit and start yet another
4197  * transaction, and do our wait before any snapshot has been taken in
4198  * it.
4199  */
4202 
4203  /*
4204  * The index is now valid in the sense that it contains all currently
4205  * interesting tuples. But since it might not contain tuples deleted
4206  * just before the reference snap was taken, we have to wait out any
4207  * transactions that might have older snapshots.
4208  *
4209  * Because we don't take a snapshot or Xid in this transaction,
4210  * there's no need to set the PROC_IN_SAFE_IC flag here.
4211  */
4214  WaitForOlderSnapshots(limitXmin, true);
4215 
4217  }
4218 
4219  /*
4220  * Phase 4 of REINDEX CONCURRENTLY
4221  *
4222  * Now that the new indexes have been validated, swap each new index with
4223  * its corresponding old index.
4224  *
4225  * We mark the new indexes as valid and the old indexes as not valid at
4226  * the same time to make sure we only get constraint violations from the
4227  * indexes with the correct names.
4228  */
4229 
4231 
4232  /*
4233  * Because this transaction only does catalog manipulations and doesn't do
4234  * any index operations, we can set the PROC_IN_SAFE_IC flag here
4235  * unconditionally.
4236  */
4238 
4239  forboth(lc, indexIds, lc2, newIndexIds)
4240  {
4241  ReindexIndexInfo *oldidx = lfirst(lc);
4242  ReindexIndexInfo *newidx = lfirst(lc2);
4243  char *oldName;
4244 
4245  /*
4246  * Check for user-requested abort. This is inside a transaction so as
4247  * xact.c does not issue a useless WARNING, and ensures that
4248  * session-level locks are cleaned up on abort.
4249  */
4251 
4252  /* Choose a relation name for old index */
4253  oldName = ChooseRelationName(get_rel_name(oldidx->indexId),
4254  NULL,
4255  "ccold",
4256  get_rel_namespace(oldidx->tableId),
4257  false);
4258 
4259  /*
4260  * Swap old index with the new one. This also marks the new one as
4261  * valid and the old one as not valid.
4262  */
4263  index_concurrently_swap(newidx->indexId, oldidx->indexId, oldName);
4264 
4265  /*
4266  * Invalidate the relcache for the table, so that after this commit
4267  * all sessions will refresh any cached plans that might reference the
4268  * index.
4269  */
4270  CacheInvalidateRelcacheByRelid(oldidx->tableId);
4271 
4272  /*
4273  * CCI here so that subsequent iterations see the oldName in the
4274  * catalog and can choose a nonconflicting name for their oldName.
4275  * Otherwise, this could lead to conflicts if a table has two indexes
4276  * whose names are equal for the first NAMEDATALEN-minus-a-few
4277  * characters.
4278  */
4280  }
4281 
4282  /* Commit this transaction and make index swaps visible */
4285 
4286  /*
4287  * While we could set PROC_IN_SAFE_IC if all indexes qualified, there's no
4288  * real need for that, because we only acquire an Xid after the wait is
4289  * done, and that lasts for a very short period.
4290  */
4291 
4292  /*
4293  * Phase 5 of REINDEX CONCURRENTLY
4294  *
4295  * Mark the old indexes as dead. First we must wait until no running
4296  * transaction could be using the index for a query. See also
4297  * index_drop() for more details.
4298  */
4299 
4303 
4304  foreach(lc, indexIds)
4305  {
4306  ReindexIndexInfo *oldidx = lfirst(lc);
4307 
4308  /*
4309  * Check for user-requested abort. This is inside a transaction so as
4310  * xact.c does not issue a useless WARNING, and ensures that
4311  * session-level locks are cleaned up on abort.
4312  */
4314 
4315  index_concurrently_set_dead(oldidx->tableId, oldidx->indexId);
4316  }
4317 
4318  /* Commit this transaction to make the updates visible. */
4321 
4322  /*
4323  * While we could set PROC_IN_SAFE_IC if all indexes qualified, there's no
4324  * real need for that, because we only acquire an Xid after the wait is
4325  * done, and that lasts for a very short period.
4326  */
4327 
4328  /*
4329  * Phase 6 of REINDEX CONCURRENTLY
4330  *
4331  * Drop the old indexes.
4332  */
4333 
4337 
4339 
4340  {
4342 
4343  foreach(lc, indexIds)
4344  {
4345  ReindexIndexInfo *idx = lfirst(lc);
4346  ObjectAddress object;
4347 
4348  object.classId = RelationRelationId;
4349  object.objectId = idx->indexId;
4350  object.objectSubId = 0;
4351 
4352  add_exact_object_address(&object, objects);
4353  }
4354 
4355  /*
4356  * Use PERFORM_DELETION_CONCURRENT_LOCK so that index_drop() uses the
4357  * right lock level.
4358  */
4361  }
4362 
4365 
4366  /*
4367  * Finally, release the session-level lock on the table.
4368  */
4369  foreach(lc, relationLocks)
4370  {
4371  LockRelId *lockrelid = (LockRelId *) lfirst(lc);
4372 
4374  }
4375 
4376  /* Start a new transaction to finish process properly */
4378 
4379  /* Log what we did */
4380  if ((params->options & REINDEXOPT_VERBOSE) != 0)
4381  {
4382  if (relkind == RELKIND_INDEX)
4383  ereport(INFO,
4384  (errmsg("index \"%s.%s\" was reindexed",
4385  relationNamespace, relationName),
4386  errdetail("%s.",
4387  pg_rusage_show(&ru0))));
4388  else
4389  {
4390  foreach(lc, newIndexIds)
4391  {
4392  ReindexIndexInfo *idx = lfirst(lc);
4393  Oid indOid = idx->indexId;
4394 
4395  ereport(INFO,
4396  (errmsg("index \"%s.%s\" was reindexed",
4398  get_rel_name(indOid))));
4399  /* Don't show rusage here, since it's not per index. */
4400  }
4401 
4402  ereport(INFO,
4403  (errmsg("table \"%s.%s\" was reindexed",
4404  relationNamespace, relationName),
4405  errdetail("%s.",
4406  pg_rusage_show(&ru0))));
4407  }
4408  }
4409 
4410  MemoryContextDelete(private_context);
4411 
4413 
4414  return true;
4415 }
4416 
4417 /*
4418  * Insert or delete an appropriate pg_inherits tuple to make the given index
4419  * be a partition of the indicated parent index.
4420  *
4421  * This also corrects the pg_depend information for the affected index.
4422  */
4423 void
4424 IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
4425 {
4426  Relation pg_inherits;
4427  ScanKeyData key[2];
4428  SysScanDesc scan;
4429  Oid partRelid = RelationGetRelid(partitionIdx);
4430  HeapTuple tuple;
4431  bool fix_dependencies;
4432 
4433  /* Make sure this is an index */
4434  Assert(partitionIdx->rd_rel->relkind == RELKIND_INDEX ||
4435  partitionIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX);
4436 
4437  /*
4438  * Scan pg_inherits for rows linking our index to some parent.
4439  */
4440  pg_inherits = relation_open(InheritsRelationId, RowExclusiveLock);
4441  ScanKeyInit(&key[0],
4442  Anum_pg_inherits_inhrelid,
4443  BTEqualStrategyNumber, F_OIDEQ,
4444  ObjectIdGetDatum(partRelid));
4445  ScanKeyInit(&key[1],
4446  Anum_pg_inherits_inhseqno,
4447  BTEqualStrategyNumber, F_INT4EQ,
4448  Int32GetDatum(1));
4449  scan = systable_beginscan(pg_inherits, InheritsRelidSeqnoIndexId, true,
4450  NULL, 2, key);
4451  tuple = systable_getnext(scan);
4452 
4453  if (!HeapTupleIsValid(tuple))
4454  {
4455  if (parentOid == InvalidOid)
4456  {
4457  /*
4458  * No pg_inherits row, and no parent wanted: nothing to do in this
4459  * case.
4460  */
4461  fix_dependencies = false;
4462  }
4463  else
4464  {
4465  StoreSingleInheritance(partRelid, parentOid, 1);
4466  fix_dependencies = true;
4467  }
4468  }
4469  else
4470  {
4471  Form_pg_inherits inhForm = (Form_pg_inherits) GETSTRUCT(tuple);
4472 
4473  if (parentOid == InvalidOid)
4474  {
4475  /*
4476  * There exists a pg_inherits row, which we want to clear; do so.
4477  */
4478  CatalogTupleDelete(pg_inherits, &tuple->t_self);
4479  fix_dependencies = true;
4480  }
4481  else
4482  {
4483  /*
4484  * A pg_inherits row exists. If it's the same we want, then we're
4485  * good; if it differs, that amounts to a corrupt catalog and
4486  * should not happen.
4487  */
4488  if (inhForm->inhparent != parentOid)
4489  {
4490  /* unexpected: we should not get called in this case */
4491  elog(ERROR, "bogus pg_inherit row: inhrelid %u inhparent %u",
4492  inhForm->inhrelid, inhForm->inhparent);
4493  }
4494 
4495  /* already in the right state */
4496  fix_dependencies = false;
4497  }
4498  }
4499 
4500  /* done with pg_inherits */
4501  systable_endscan(scan);
4502  relation_close(pg_inherits, RowExclusiveLock);
4503 
4504  /* set relhassubclass if an index partition has been added to the parent */
4505  if (OidIsValid(parentOid))
4506  {
4508  SetRelationHasSubclass(parentOid, true);
4509  }
4510 
4511  /* set relispartition correctly on the partition */
4512  update_relispartition(partRelid, OidIsValid(parentOid));
4513 
4514  if (fix_dependencies)
4515  {
4516  /*
4517  * Insert/delete pg_depend rows. If setting a parent, add PARTITION
4518  * dependencies on the parent index and the table; if removing a
4519  * parent, delete PARTITION dependencies.
4520  */
4521  if (OidIsValid(parentOid))
4522  {
4523  ObjectAddress partIdx;
4524  ObjectAddress parentIdx;
4525  ObjectAddress partitionTbl;
4526 
4527  ObjectAddressSet(partIdx, RelationRelationId, partRelid);
4528  ObjectAddressSet(parentIdx, RelationRelationId, parentOid);
4529  ObjectAddressSet(partitionTbl, RelationRelationId,
4530  partitionIdx->rd_index->indrelid);
4531  recordDependencyOn(&partIdx, &parentIdx,
4533  recordDependencyOn(&partIdx, &partitionTbl,
4535  }
4536  else
4537  {
4538  deleteDependencyRecordsForClass(RelationRelationId, partRelid,
4539  RelationRelationId,
4541  deleteDependencyRecordsForClass(RelationRelationId, partRelid,
4542  RelationRelationId,
4544  }
4545 
4546  /* make our updates visible */
4548  }
4549 }
4550 
4551 /*
4552  * Subroutine of IndexSetParentIndex to update the relispartition flag of the
4553  * given index to the given value.
4554  */
4555 static void
4557 {
4558  HeapTuple tup;
4559  Relation classRel;
4560 
4561  classRel = table_open(RelationRelationId, RowExclusiveLock);
4562  tup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
4563  if (!HeapTupleIsValid(tup))
4564  elog(ERROR, "cache lookup failed for relation %u", relationId);
4565  Assert(((Form_pg_class) GETSTRUCT(tup))->relispartition != newval);
4566  ((Form_pg_class) GETSTRUCT(tup))->relispartition = newval;
4567  CatalogTupleUpdate(classRel, &tup->t_self, tup);
4568  heap_freetuple(tup);
4569  table_close(classRel, RowExclusiveLock);
4570 }
4571 
4572 /*
4573  * Set the PROC_IN_SAFE_IC flag in MyProc->statusFlags.
4574  *
4575  * When doing concurrent index builds, we can set this flag
4576  * to tell other processes concurrently running CREATE
4577  * INDEX CONCURRENTLY or REINDEX CONCURRENTLY to ignore us when
4578  * doing their waits for concurrent snapshots. On one hand it
4579  * avoids pointlessly waiting for a process that's not interesting
4580  * anyway; but more importantly it avoids deadlocks in some cases.
4581  *
4582  * This can be done safely only for indexes that don't execute any
4583  * expressions that could access other tables, so index must not be
4584  * expressional nor partial. Caller is responsible for only calling
4585  * this routine when that assumption holds true.
4586  *
4587  * (The flag is reset automatically at transaction end, so it must be
4588  * set for each transaction.)
4589  */
4590 static inline void
4592 {
4593  /*
4594  * This should only be called before installing xid or xmin in MyProc;
4595  * otherwise, concurrent processes could see an Xmin that moves backwards.
4596  */
4599 
4600  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4603  LWLockRelease(ProcArrayLock);
4604 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5268
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2698
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3886
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4140
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4089
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
bytea *(* amoptions_function)(Datum reloptions, bool validate)
Definition: amapi.h:151
Datum array_eq(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:3802
void free_attrmap(AttrMap *map)
Definition: attmap.c:56
AttrMap * build_attrmap_by_name(TupleDesc indesc, TupleDesc outdesc, bool missing_ok)
Definition: attmap.c:177
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1472
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1426
Oid GetDefaultTablespace(char relpersistence, bool partitioned)
Definition: tablespace.c:1143
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
void pgstat_progress_incr_param(int index, int64 incr)
void pgstat_progress_update_param(int index, int64 val)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
void pgstat_progress_end_command(void)
@ PROGRESS_COMMAND_CREATE_INDEX
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
#define NameStr(name)
Definition: c.h:746
unsigned short uint16
Definition: c.h:505
uint16 bits16
Definition: c.h:514
signed short int16
Definition: c.h:493
#define InvalidSubTransactionId
Definition: c.h:658
#define Assert(condition)
Definition: c.h:858
uint32 TransactionId
Definition: c.h:652
#define OidIsValid(objectId)
Definition: c.h:775
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:221
bool IsSystemRelation(Relation relation)
Definition: catalog.c:73
bool IsCatalogRelationOid(Oid relid)
Definition: catalog.c:120
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:85
bool contain_mutable_functions_after_planning(Expr *expr)
Definition: clauses.c:490
void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment)
Definition: comment.c:143
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3184
bool defGetBoolean(DefElem *def)
Definition: define.c:107
char * defGetString(DefElem *def)
Definition: define.c:48
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:332
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2487
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2533
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
#define PERFORM_DELETION_CONCURRENT_LOCK
Definition: dependency.h:97
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:92
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errdetail(const char *fmt,...)
Definition: elog.c:1203
ErrorContextCallback * error_context_stack
Definition: elog.c:94
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define errcontext
Definition: elog.h:196
#define WARNING
Definition: elog.h:36
#define DEBUG1
Definition: elog.h:30
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define NOTICE
Definition: elog.h:35
#define INFO
Definition: elog.h:34
#define ereport(elevel,...)
Definition: elog.h:149
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
#define palloc_object(type)
Definition: fe_memutils.h:62
#define palloc_array(type, count)
Definition: fe_memutils.h:64
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:602
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:509
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:385
StrategyNumber GistTranslateStratnum(Oid opclass, StrategyNumber strat)
Definition: gistutil.c:1081
bool allowSystemTableMods
Definition: globals.c:129
Oid MyDatabaseTableSpace
Definition: globals.c:95
Oid MyDatabaseId
Definition: globals.c:93
int NewGUCNestLevel(void)
Definition: guc.c:2234
#define newval
void RestrictSearchPath(void)
Definition: guc.c:2245
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:2261
int set_config_option(const char *name, const char *value, GucContext context, GucSource source, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition: guc.c:3342
@ GUC_ACTION_SAVE
Definition: guc.h:201
@ PGC_S_SESSION
Definition: guc.h:122
@ PGC_USERSET
Definition: guc.h:75
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1234
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:455
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define stmt
Definition: indent_codes.h:59
int verbose
void validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
Definition: index.c:3298
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3531
void index_concurrently_set_dead(Oid heapId, Oid indexId)
Definition: index.c:1821
Oid index_create(Relation heapRelation, const char *indexRelationName, Oid indexRelationId, Oid parentIndexRelid, Oid parentConstraintId, RelFileNumber relFileNumber, IndexInfo *indexInfo, const List *indexColNames, Oid accessMethodId, Oid tableSpaceId, const Oid *collationIds, const Oid *opclassIds, const Datum *opclassOptions, const int16 *coloptions, const NullableDatum *stattargets, Datum reloptions, bits16 flags, bits16 constr_flags, bool allow_system_table_mods, bool is_internal, Oid *constraintId)
Definition: index.c:724
void index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
Definition: index.c:1550
void index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
Definition: index.c:3451
bool CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2, const Oid *collations1, const Oid *collations2, const Oid *opfamilies1, const Oid *opfamilies2, const AttrMap *attmap)
Definition: index.c:2518
bool reindex_relation(const ReindexStmt *stmt, Oid relid, int flags, const ReindexParams *params)
Definition: index.c:3896
Oid index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, Oid tablespaceOid, const char *newName)
Definition: index.c:1298
void index_check_primary_key(Relation heapRel, const IndexInfo *indexInfo, bool is_alter_table, const IndexStmt *stmt)
Definition: index.c:201
void index_concurrently_build(Oid heapRelationId, Oid indexRelationId)
Definition: index.c:1483
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:2409
void reindex_index(const ReindexStmt *stmt, Oid indexId, bool skip_constraint_checks, char persistence, const ReindexParams *params)
Definition: index.c:3556
#define INDEX_CREATE_IS_PRIMARY
Definition: index.h:61
#define INDEX_CREATE_IF_NOT_EXISTS
Definition: index.h:65
#define REINDEX_REL_PROCESS_TOAST
Definition: index.h:159
#define INDEX_CREATE_PARTITIONED
Definition: index.h:66
#define REINDEXOPT_CONCURRENTLY
Definition: index.h:44
#define REINDEXOPT_MISSING_OK
Definition: index.h:43
#define INDEX_CREATE_INVALID
Definition: index.h:67
#define INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS
Definition: index.h:96
#define INDEX_CREATE_ADD_CONSTRAINT
Definition: index.h:62
#define INDEX_CREATE_SKIP_BUILD
Definition: index.h:63
#define INDEX_CONSTR_CREATE_DEFERRABLE
Definition: index.h:92
#define REINDEXOPT_REPORT_PROGRESS
Definition: index.h:42
@ INDEX_CREATE_SET_VALID
Definition: index.h:27
#define INDEX_CONSTR_CREATE_INIT_DEFERRED
Definition: index.h:93
#define INDEX_CREATE_CONCURRENT
Definition: index.h:64
#define REINDEXOPT_VERBOSE
Definition: index.h:41
#define REINDEX_REL_CHECK_CONSTRAINTS
Definition: index.h:161
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:133
static bool ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const ReindexParams *params)
Definition: indexcmds.c:3565
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:2549
void ExecReindex(ParseState *pstate, const ReindexStmt *stmt, bool isTopLevel)
Definition: indexcmds.c:2821
ObjectAddress DefineIndex(Oid tableId, IndexStmt *stmt, Oid indexRelationId, Oid parentIndexId, Oid parentConstraintId, int total_parts, bool is_alter_table, bool check_rights, bool check_not_in_use, bool skip_build, bool quiet)
Definition: indexcmds.c:536
static void set_indexsafe_procflags(void)
Definition: indexcmds.c:4591
static void reindex_error_callback(void *arg)
Definition: indexcmds.c:3324
static void ComputeIndexAttrs(IndexInfo *indexInfo, Oid *typeOids, Oid *collationOids, Oid *opclassOids, Datum *opclassOptions, int16 *colOptions, const List *attList, const List *exclusionOpNames, Oid relId, const char *accessMethodName, Oid accessMethodId, bool amcanorder, bool isconstraint, bool iswithoutoverlaps, Oid ddl_userid, int ddl_sec_context, int *ddl_save_nestlevel)
Definition: indexcmds.c:1866
static void ReindexIndex(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel)
Definition: indexcmds.c:2916
void IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
Definition: indexcmds.c:4424
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2358
static char * ChooseIndexNameAddition(const List *colnames)
Definition: indexcmds.c:2726
static void ReindexMultipleTables(const ReindexStmt *stmt, const ReindexParams *params)
Definition: indexcmds.c:3105
static bool CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts)
Definition: indexcmds.c:362
static void update_relispartition(Oid relationId, bool newval)
Definition: indexcmds.c:4556
bool CheckIndexCompatible(Oid oldId, const char *accessMethodName, const List *attributeList, const List *exclusionOpNames, bool isWithoutOverlaps)
Definition: indexcmds.c:178
void GetOperatorFromWellKnownStrategy(Oid opclass, Oid rhstype, Oid *opid, StrategyNumber *strat)
Definition: indexcmds.c:2461
void WaitForOlderSnapshots(TransactionId limitXmin, bool progress)
Definition: indexcmds.c:429
Oid ResolveOpClass(const List *opclass, Oid attrType, const char *accessMethodName, Oid accessMethodId)
Definition: indexcmds.c:2273
static void ReindexPartitions(const ReindexStmt *stmt, Oid relid, const ReindexParams *params, bool isTopLevel)
Definition: indexcmds.c:3345
struct ReindexErrorInfo ReindexErrorInfo
static Oid ReindexTable(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel)
Definition: indexcmds.c:3046
static void CheckPredicate(Expr *predicate)
Definition: indexcmds.c:1839
static void ReindexMultipleInternal(const ReindexStmt *stmt, const List *relids, const ReindexParams *params)
Definition: indexcmds.c:3439
static void RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: indexcmds.c:2970
static List * ChooseIndexColumnNames(const List *indexElems)
Definition: indexcmds.c:2760
static char * ChooseIndexName(const char *tabname, Oid namespaceId, const List *colnames, const List *exclusionOpNames, bool primary, bool isconstraint)
Definition: indexcmds.c:2671
char * ChooseRelationName(const char *name1, const char *name2, const char *label, Oid namespaceid, bool isconstraint)
Definition: indexcmds.c:2635
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
#define INJECTION_POINT(name)
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1419
int j
Definition: isn.c:74
int i
Definition: isn.c:73
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
void list_free(List *list)
Definition: list.c:1546
List * lcons_oid(Oid datum, List *list)
Definition: list.c:531
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:598
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:227
void WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress)
Definition: lmgr.c:897
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:387
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress)
Definition: lmgr.c:975
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:400
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4549
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:67
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:181
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:71
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:74
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
#define AccessShareLock
Definition: lockdefs.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define ShareLock
Definition: lockdefs.h:40
#define RowExclusiveLock
Definition: lockdefs.h:38
char get_rel_persistence(Oid relid)
Definition: lsyscache.c:2078
char * get_opname(Oid opno)
Definition: lsyscache.c:1310
bool get_index_isvalid(Oid index_oid)
Definition: lsyscache.c:3578
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1212
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1190
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition: lsyscache.c:1235
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:970
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2003
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1952
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1285
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:83
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:166
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:3081
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2521
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1885
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1509
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:1358
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_EXCLUSIVE
Definition: lwlock.h:114
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:737
IndexInfo * makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, List *predicates, bool unique, bool nulls_not_distinct, bool isready, bool concurrent, bool summarizing, bool withoutoverlaps)
Definition: makefuncs.c:761
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1083
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
void * palloc(Size size)
Definition: mcxt.c:1317
MemoryContext PortalContext
Definition: mcxt.c:158
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:451
#define SECURITY_RESTRICTED_OPERATION
Definition: miscadmin.h:312
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:635
Oid GetUserId(void)
Definition: miscinit.c:514
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:642
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
Definition: namespace.c:2106
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:3370
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3634
Oid get_collation_oid(List *collname, bool missing_ok)
Definition: namespace.c:3956
void DeconstructQualifiedName(const List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:3286
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3520
char * NameListToString(const List *names)
Definition: namespace.c:3579
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:426
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:816
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:224
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
TYPCATEGORY TypeCategory(Oid type)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
bool IsPreferredType(TYPCATEGORY category, Oid type)
char TYPCATEGORY
Definition: parse_coerce.h:21
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
Definition: parse_oper.c:487
@ SORTBY_NULLS_DEFAULT
Definition: parsenodes.h:54
@ SORTBY_NULLS_FIRST
Definition: parsenodes.h:55
#define ACL_MAINTAIN
Definition: parsenodes.h:90
@ PARTITION_STRATEGY_HASH
Definition: parsenodes.h:876
@ DROP_RESTRICT
Definition: parsenodes.h:2330
@ OBJECT_SCHEMA
Definition: parsenodes.h:2293
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2299
@ OBJECT_INDEX
Definition: parsenodes.h:2277
@ OBJECT_DATABASE
Definition: parsenodes.h:2266
ReindexObjectType
Definition: parsenodes.h:3969
@ REINDEX_OBJECT_DATABASE
Definition: parsenodes.h:3974
@ REINDEX_OBJECT_INDEX
Definition: parsenodes.h:3970
@ REINDEX_OBJECT_SCHEMA
Definition: parsenodes.h:3972
@ REINDEX_OBJECT_SYSTEM
Definition: parsenodes.h:3973
@ REINDEX_OBJECT_TABLE
Definition: parsenodes.h:3971
#define ACL_CREATE
Definition: parsenodes.h:85
@ SORTBY_DESC
Definition: parsenodes.h:48
@ SORTBY_DEFAULT
Definition: parsenodes.h:46
PartitionKey RelationGetPartitionKey(Relation rel)
Definition: partcache.c:51
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
Definition: partdesc.c:71
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
static void fix_dependencies(ArchiveHandle *AH)
void * arg
static char * label
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define INDEX_MAX_KEYS
#define NAMEDATALEN
Oid get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
void ConstraintSetParentConstraint(Oid childConstrId, Oid parentConstrId, Oid childTableId)
bool ConstraintNameExists(const char *conname, Oid namespaceid)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:352
FormData_pg_index * Form_pg_index
Definition: pg_index.h:70
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:255
void StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber)
Definition: pg_inherits.c:508
bool has_superclass(Oid relationId)
Definition: pg_inherits.c:377
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:45
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
#define list_make1_oid(x1)
Definition: pg_list.h:242
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
#define lfirst_oid(lc)
Definition: pg_list.h:174
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:51
const char * pg_rusage_show(const PGRUsage *ru0)
Definition: pg_rusage.c:40
void pg_rusage_init(PGRUsage *ru0)
Definition: pg_rusage.c:27
static char * buf
Definition: pg_test_fsync.c:73
static int progress
Definition: pgbench.c:261
static int partitions
Definition: pgbench.c:223
#define sprintf
Definition: port.h:240
#define snprintf
Definition: port.h:238
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define PROC_IN_SAFE_IC
Definition: proc.h:59
#define PROC_IN_VACUUM
Definition: proc.h:58
#define PROC_IS_AUTOVACUUM
Definition: proc.h:57
PGPROC * ProcNumberGetProc(ProcNumber procNumber)
Definition: procarray.c:3142
VirtualTransactionId * GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
Definition: procarray.c:3328
#define PROGRESS_CREATEIDX_PHASE_WAIT_4
Definition: progress.h:101
#define PROGRESS_CREATEIDX_PHASE_BUILD
Definition: progress.h:95
#define PROGRESS_CREATEIDX_PARTITIONS_DONE
Definition: progress.h:90
#define PROGRESS_CREATEIDX_PHASE_WAIT_1
Definition: progress.h:94
#define PROGRESS_CREATEIDX_COMMAND_CREATE_CONCURRENTLY
Definition: progress.h:112
#define PROGRESS_CREATEIDX_ACCESS_METHOD_OID
Definition: progress.h:84
#define PROGRESS_WAITFOR_DONE
Definition: progress.h:118
#define PROGRESS_CREATEIDX_PHASE_WAIT_3
Definition: progress.h:100
#define PROGRESS_WAITFOR_TOTAL
Definition: progress.h:117
#define PROGRESS_CREATEIDX_COMMAND_REINDEX_CONCURRENTLY
Definition: progress.h:114
#define PROGRESS_CREATEIDX_COMMAND_CREATE
Definition: progress.h:111
#define PROGRESS_WAITFOR_CURRENT_PID
Definition: progress.h:119
#define PROGRESS_CREATEIDX_PHASE_WAIT_2
Definition: progress.h:96
#define PROGRESS_CREATEIDX_PHASE
Definition: progress.h:85
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN
Definition: progress.h:97
#define PROGRESS_CREATEIDX_PHASE_WAIT_5
Definition: progress.h:102
#define PROGRESS_CREATEIDX_INDEX_OID
Definition: progress.h:83
#define PROGRESS_CREATEIDX_PARTITIONS_TOTAL
Definition: progress.h:89
#define PROGRESS_CREATEIDX_COMMAND
Definition: progress.h:82
MemoryContextSwitchTo(old_ctx)
char * format_operator(Oid operator_oid)
Definition: regproc.c:793
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:658
#define RelationGetNamespace(relation)
Definition: rel.h:546
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4801
List * RelationGetIndexPredicate(Relation relation)
Definition: relcache.c:5151
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition: relcache.c:5594
List * RelationGetIndexExpressions(Relation relation)
Definition: relcache.c:5038
bytea * index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
Definition: reloptions.c:2054
Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, const char *const validnsps[], bool acceptOidsOff, bool isReset)
Definition: reloptions.c:1156
#define InvalidRelFileNumber
Definition: relpath.h:26
#define RelFileNumberIsValid(relnumber)
Definition: relpath.h:27
Node * map_variable_attnos(Node *node, int target_varno, int sublevels_up, const AttrMap *attno_map, Oid to_rowtype, bool *found_whole_row)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
@ ForwardScanDirection
Definition: sdir.h:28
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:216
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:836
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:648
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:782
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:794
void PopActiveSnapshot(void)
Definition: snapmgr.c:743
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:79
uint16 StrategyNumber
Definition: stratnum.h:22
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define RTEqualStrategyNumber
Definition: stratnum.h:68
#define InvalidStrategy
Definition: stratnum.h:24
#define HTEqualStrategyNumber
Definition: stratnum.h:41
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Definition: attmap.h:35
char * defname
Definition: parsenodes.h:817
ParseLoc location
Definition: parsenodes.h:821
struct ErrorContextCallback * previous
Definition: elog.h:296
void(* callback)(void *arg)
Definition: elog.h:297
ItemPointerData t_self
Definition: htup.h:65
amoptions_function amoptions
Definition: amapi.h:283
amgettuple_function amgettuple
Definition: amapi.h:290
bool amcanunique
Definition: amapi.h:237
bool amsummarizing
Definition: amapi.h:261
bool amcanmulticol
Definition: amapi.h:239
bool amcanorder
Definition: amapi.h:231
bool amcaninclude
Definition: amapi.h:257
Node * expr
Definition: parsenodes.h:786
SortByDir ordering
Definition: parsenodes.h:791
List * opclassopts
Definition: parsenodes.h:790
char * indexcolname
Definition: parsenodes.h:787
SortByNulls nulls_ordering
Definition: parsenodes.h:792
List * opclass
Definition: parsenodes.h:789
char * name
Definition: parsenodes.h:785
List * collation
Definition: parsenodes.h:788
uint16 * ii_ExclusionStrats
Definition: execnodes.h:195
int ii_NumIndexAttrs
Definition: execnodes.h:186
Oid * ii_ExclusionOps
Definition: execnodes.h:193
int ii_NumIndexKeyAttrs
Definition: execnodes.h:187
List * ii_Expressions
Definition: execnodes.h:189
Oid * ii_ExclusionProcs
Definition: execnodes.h:194
AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:188
List * ii_Predicate
Definition: execnodes.h:191
List * indexParams
Definition: parsenodes.h:3357
Oid indexOid
Definition: parsenodes.h:3364
RangeVar * relation
Definition: parsenodes.h:3354
SubTransactionId oldFirstRelfilelocatorSubid
Definition: parsenodes.h:3367
SubTransactionId oldCreateSubid
Definition: parsenodes.h:3366
char * idxname
Definition: parsenodes.h:3353
Node * whereClause
Definition: parsenodes.h:3361
RelFileNumber oldNumber
Definition: parsenodes.h:3365
Definition: lock.h:165
Definition: pg_list.h:54
LockRelId lockRelId
Definition: rel.h:46
Definition: rel.h:39
Oid relId
Definition: rel.h:40
Oid dbId
Definition: rel.h:41
Definition: nodes.h:129
Definition: proc.h:157
TransactionId xmin
Definition: proc.h:172
uint8 statusFlags
Definition: proc.h:237
int pid
Definition: proc.h:177
int pgxactoff
Definition: proc.h:179
TransactionId xid
Definition: proc.h:167
uint8 * statusFlags
Definition: proc.h:394
char * relname
Definition: primnodes.h:82
char * relnamespace
Definition: indexcmds.c:135
ReindexParams params
Definition: indexcmds.c:125
Oid tablespaceOid
Definition: index.h:36
bits32 options
Definition: index.h:35
LockInfoData rd_lockInfo
Definition: rel.h:114
TupleDesc rd_att
Definition: rel.h:112
Form_pg_index rd_index
Definition: rel.h:192
Oid * rd_opfamily
Definition: rel.h:207
Oid * rd_indcollation
Definition: rel.h:217
Form_pg_class rd_rel
Definition: rel.h:111
TransactionId xmin
Definition: snapshot.h:157
Definition: primnodes.h:248
Definition: c.h:726
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:733
Definition: regguts.h:323
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:240
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:359
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:510
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:86
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:95
Relation try_table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:60
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1019
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:4246
void SetRelationHasSubclass(Oid relationId, bool relhassubclass)
Definition: tablecmds.c:3486
void RangeVarCallbackMaintainsTable(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: tablecmds.c:17707
#define InvalidTransactionId
Definition: transam.h:31
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:296
const char * name
void CommandCounterIncrement(void)
Definition: xact.c:1099
void PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
Definition: xact.c:3628
void StartTransactionCommand(void)
Definition: xact.c:3039
void CommitTransactionCommand(void)
Definition: xact.c:3137