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