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-2020, 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_constraint.h"
30 #include "catalog/pg_inherits.h"
31 #include "catalog/pg_opclass.h"
32 #include "catalog/pg_opfamily.h"
33 #include "catalog/pg_tablespace.h"
34 #include "catalog/pg_type.h"
35 #include "commands/comment.h"
36 #include "commands/dbcommands.h"
37 #include "commands/defrem.h"
38 #include "commands/event_trigger.h"
39 #include "commands/progress.h"
40 #include "commands/tablecmds.h"
41 #include "commands/tablespace.h"
42 #include "mb/pg_wchar.h"
43 #include "miscadmin.h"
44 #include "nodes/makefuncs.h"
45 #include "nodes/nodeFuncs.h"
46 #include "optimizer/optimizer.h"
47 #include "parser/parse_coerce.h"
48 #include "parser/parse_func.h"
49 #include "parser/parse_oper.h"
50 #include "partitioning/partdesc.h"
51 #include "pgstat.h"
52 #include "rewrite/rewriteManip.h"
53 #include "storage/lmgr.h"
54 #include "storage/proc.h"
55 #include "storage/procarray.h"
56 #include "storage/sinvaladt.h"
57 #include "utils/acl.h"
58 #include "utils/builtins.h"
59 #include "utils/fmgroids.h"
60 #include "utils/inval.h"
61 #include "utils/lsyscache.h"
62 #include "utils/memutils.h"
63 #include "utils/partcache.h"
64 #include "utils/pg_rusage.h"
65 #include "utils/regproc.h"
66 #include "utils/snapmgr.h"
67 #include "utils/syscache.h"
68 
69 
70 /* non-export function prototypes */
71 static void CheckPredicate(Expr *predicate);
72 static void ComputeIndexAttrs(IndexInfo *indexInfo,
73  Oid *typeOidP,
74  Oid *collationOidP,
75  Oid *classOidP,
76  int16 *colOptionP,
77  List *attList,
78  List *exclusionOpNames,
79  Oid relId,
80  const char *accessMethodName, Oid accessMethodId,
81  bool amcanorder,
82  bool isconstraint);
83 static char *ChooseIndexName(const char *tabname, Oid namespaceId,
84  List *colnames, List *exclusionOpNames,
85  bool primary, bool isconstraint);
86 static char *ChooseIndexNameAddition(List *colnames);
87 static List *ChooseIndexColumnNames(List *indexElems);
88 static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
89  Oid relId, Oid oldRelId, void *arg);
90 static bool ReindexRelationConcurrently(Oid relationOid, int options);
91 static void ReindexPartitionedIndex(Relation parentIdx);
92 static void update_relispartition(Oid relationId, bool newval);
93 
94 /*
95  * callback argument type for RangeVarCallbackForReindexIndex()
96  */
98 {
99  bool concurrent; /* flag from statement */
100  Oid locked_table_oid; /* tracks previously locked table */
101 };
102 
103 /*
104  * CheckIndexCompatible
105  * Determine whether an existing index definition is compatible with a
106  * prospective index definition, such that the existing index storage
107  * could become the storage of the new index, avoiding a rebuild.
108  *
109  * 'heapRelation': the relation the index would apply to.
110  * 'accessMethodName': name of the AM to use.
111  * 'attributeList': a list of IndexElem specifying columns and expressions
112  * to index on.
113  * 'exclusionOpNames': list of names of exclusion-constraint operators,
114  * or NIL if not an exclusion constraint.
115  *
116  * This is tailored to the needs of ALTER TABLE ALTER TYPE, which recreates
117  * any indexes that depended on a changing column from their pg_get_indexdef
118  * or pg_get_constraintdef definitions. We omit some of the sanity checks of
119  * DefineIndex. We assume that the old and new indexes have the same number
120  * of columns and that if one has an expression column or predicate, both do.
121  * Errors arising from the attribute list still apply.
122  *
123  * Most column type changes that can skip a table rewrite do not invalidate
124  * indexes. We acknowledge this when all operator classes, collations and
125  * exclusion operators match. Though we could further permit intra-opfamily
126  * changes for btree and hash indexes, that adds subtle complexity with no
127  * concrete benefit for core types. Note, that INCLUDE columns aren't
128  * checked by this function, for them it's enough that table rewrite is
129  * skipped.
130  *
131  * When a comparison or exclusion operator has a polymorphic input type, the
132  * actual input types must also match. This defends against the possibility
133  * that operators could vary behavior in response to get_fn_expr_argtype().
134  * At present, this hazard is theoretical: check_exclusion_constraint() and
135  * all core index access methods decline to set fn_expr for such calls.
136  *
137  * We do not yet implement a test to verify compatibility of expression
138  * columns or predicates, so assume any such index is incompatible.
139  */
140 bool
142  const char *accessMethodName,
143  List *attributeList,
144  List *exclusionOpNames)
145 {
146  bool isconstraint;
147  Oid *typeObjectId;
148  Oid *collationObjectId;
149  Oid *classObjectId;
150  Oid accessMethodId;
151  Oid relationId;
152  HeapTuple tuple;
153  Form_pg_index indexForm;
154  Form_pg_am accessMethodForm;
155  IndexAmRoutine *amRoutine;
156  bool amcanorder;
157  int16 *coloptions;
158  IndexInfo *indexInfo;
159  int numberOfAttributes;
160  int old_natts;
161  bool isnull;
162  bool ret = true;
163  oidvector *old_indclass;
164  oidvector *old_indcollation;
165  Relation irel;
166  int i;
167  Datum d;
168 
169  /* Caller should already have the relation locked in some way. */
170  relationId = IndexGetRelation(oldId, false);
171 
172  /*
173  * We can pretend isconstraint = false unconditionally. It only serves to
174  * decide the text of an error message that should never happen for us.
175  */
176  isconstraint = false;
177 
178  numberOfAttributes = list_length(attributeList);
179  Assert(numberOfAttributes > 0);
180  Assert(numberOfAttributes <= INDEX_MAX_KEYS);
181 
182  /* look up the access method */
183  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
184  if (!HeapTupleIsValid(tuple))
185  ereport(ERROR,
186  (errcode(ERRCODE_UNDEFINED_OBJECT),
187  errmsg("access method \"%s\" does not exist",
188  accessMethodName)));
189  accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
190  accessMethodId = accessMethodForm->oid;
191  amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
192  ReleaseSysCache(tuple);
193 
194  amcanorder = amRoutine->amcanorder;
195 
196  /*
197  * Compute the operator classes, collations, and exclusion operators for
198  * the new index, so we can test whether it's compatible with the existing
199  * one. Note that ComputeIndexAttrs might fail here, but that's OK:
200  * DefineIndex would have called this function with the same arguments
201  * later on, and it would have failed then anyway. Our attributeList
202  * contains only key attributes, thus we're filling ii_NumIndexAttrs and
203  * ii_NumIndexKeyAttrs with same value.
204  */
205  indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
206  accessMethodId, NIL, NIL, false, false, false);
207  typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
208  collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
209  classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
210  coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16));
211  ComputeIndexAttrs(indexInfo,
212  typeObjectId, collationObjectId, classObjectId,
213  coloptions, attributeList,
214  exclusionOpNames, relationId,
215  accessMethodName, accessMethodId,
216  amcanorder, isconstraint);
217 
218 
219  /* Get the soon-obsolete pg_index tuple. */
221  if (!HeapTupleIsValid(tuple))
222  elog(ERROR, "cache lookup failed for index %u", oldId);
223  indexForm = (Form_pg_index) GETSTRUCT(tuple);
224 
225  /*
226  * We don't assess expressions or predicates; assume incompatibility.
227  * Also, if the index is invalid for any reason, treat it as incompatible.
228  */
229  if (!(heap_attisnull(tuple, Anum_pg_index_indpred, NULL) &&
230  heap_attisnull(tuple, Anum_pg_index_indexprs, NULL) &&
231  indexForm->indisvalid))
232  {
233  ReleaseSysCache(tuple);
234  return false;
235  }
236 
237  /* Any change in operator class or collation breaks compatibility. */
238  old_natts = indexForm->indnkeyatts;
239  Assert(old_natts == numberOfAttributes);
240 
241  d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indcollation, &isnull);
242  Assert(!isnull);
243  old_indcollation = (oidvector *) DatumGetPointer(d);
244 
245  d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indclass, &isnull);
246  Assert(!isnull);
247  old_indclass = (oidvector *) DatumGetPointer(d);
248 
249  ret = (memcmp(old_indclass->values, classObjectId,
250  old_natts * sizeof(Oid)) == 0 &&
251  memcmp(old_indcollation->values, collationObjectId,
252  old_natts * sizeof(Oid)) == 0);
253 
254  ReleaseSysCache(tuple);
255 
256  if (!ret)
257  return false;
258 
259  /* For polymorphic opcintype, column type changes break compatibility. */
260  irel = index_open(oldId, AccessShareLock); /* caller probably has a lock */
261  for (i = 0; i < old_natts; i++)
262  {
263  if (IsPolymorphicType(get_opclass_input_type(classObjectId[i])) &&
264  TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i])
265  {
266  ret = false;
267  break;
268  }
269  }
270 
271  /* Any change in exclusion operator selections breaks compatibility. */
272  if (ret && indexInfo->ii_ExclusionOps != NULL)
273  {
274  Oid *old_operators,
275  *old_procs;
276  uint16 *old_strats;
277 
278  RelationGetExclusionInfo(irel, &old_operators, &old_procs, &old_strats);
279  ret = memcmp(old_operators, indexInfo->ii_ExclusionOps,
280  old_natts * sizeof(Oid)) == 0;
281 
282  /* Require an exact input type match for polymorphic operators. */
283  if (ret)
284  {
285  for (i = 0; i < old_natts && ret; i++)
286  {
287  Oid left,
288  right;
289 
290  op_input_types(indexInfo->ii_ExclusionOps[i], &left, &right);
291  if ((IsPolymorphicType(left) || IsPolymorphicType(right)) &&
292  TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i])
293  {
294  ret = false;
295  break;
296  }
297  }
298  }
299  }
300 
301  index_close(irel, NoLock);
302  return ret;
303 }
304 
305 
306 /*
307  * WaitForOlderSnapshots
308  *
309  * Wait for transactions that might have an older snapshot than the given xmin
310  * limit, because it might not contain tuples deleted just before it has
311  * been taken. Obtain a list of VXIDs of such transactions, and wait for them
312  * individually. This is used when building an index concurrently.
313  *
314  * We can exclude any running transactions that have xmin > the xmin given;
315  * their oldest snapshot must be newer than our xmin limit.
316  * We can also exclude any transactions that have xmin = zero, since they
317  * evidently have no live snapshot at all (and any one they might be in
318  * process of taking is certainly newer than ours). Transactions in other
319  * DBs can be ignored too, since they'll never even be able to see the
320  * index being worked on.
321  *
322  * We can also exclude autovacuum processes and processes running manual
323  * lazy VACUUMs, because they won't be fazed by missing index entries
324  * either. (Manual ANALYZEs, however, can't be excluded because they
325  * might be within transactions that are going to do arbitrary operations
326  * later.)
327  *
328  * Also, GetCurrentVirtualXIDs never reports our own vxid, so we need not
329  * check for that.
330  *
331  * If a process goes idle-in-transaction with xmin zero, we do not need to
332  * wait for it anymore, per the above argument. We do not have the
333  * infrastructure right now to stop waiting if that happens, but we can at
334  * least avoid the folly of waiting when it is idle at the time we would
335  * begin to wait. We do this by repeatedly rechecking the output of
336  * GetCurrentVirtualXIDs. If, during any iteration, a particular vxid
337  * doesn't show up in the output, we know we can forget about it.
338  */
339 static void
341 {
342  int n_old_snapshots;
343  int i;
344  VirtualTransactionId *old_snapshots;
345 
346  old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
348  &n_old_snapshots);
349  if (progress)
351 
352  for (i = 0; i < n_old_snapshots; i++)
353  {
354  if (!VirtualTransactionIdIsValid(old_snapshots[i]))
355  continue; /* found uninteresting in previous cycle */
356 
357  if (i > 0)
358  {
359  /* see if anything's changed ... */
360  VirtualTransactionId *newer_snapshots;
361  int n_newer_snapshots;
362  int j;
363  int k;
364 
365  newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
366  true, false,
368  &n_newer_snapshots);
369  for (j = i; j < n_old_snapshots; j++)
370  {
371  if (!VirtualTransactionIdIsValid(old_snapshots[j]))
372  continue; /* found uninteresting in previous cycle */
373  for (k = 0; k < n_newer_snapshots; k++)
374  {
375  if (VirtualTransactionIdEquals(old_snapshots[j],
376  newer_snapshots[k]))
377  break;
378  }
379  if (k >= n_newer_snapshots) /* not there anymore */
380  SetInvalidVirtualTransactionId(old_snapshots[j]);
381  }
382  pfree(newer_snapshots);
383  }
384 
385  if (VirtualTransactionIdIsValid(old_snapshots[i]))
386  {
387  /* If requested, publish who we're going to wait for. */
388  if (progress)
389  {
390  PGPROC *holder = BackendIdGetProc(old_snapshots[i].backendId);
391 
392  if (holder)
394  holder->pid);
395  }
396  VirtualXactLock(old_snapshots[i], true);
397  }
398 
399  if (progress)
401  }
402 }
403 
404 
405 /*
406  * DefineIndex
407  * Creates a new index.
408  *
409  * 'relationId': the OID of the heap relation on which the index is to be
410  * created
411  * 'stmt': IndexStmt describing the properties of the new index.
412  * 'indexRelationId': normally InvalidOid, but during bootstrap can be
413  * nonzero to specify a preselected OID for the index.
414  * 'parentIndexId': the OID of the parent index; InvalidOid if not the child
415  * of a partitioned index.
416  * 'parentConstraintId': the OID of the parent constraint; InvalidOid if not
417  * the child of a constraint (only used when recursing)
418  * 'is_alter_table': this is due to an ALTER rather than a CREATE operation.
419  * 'check_rights': check for CREATE rights in namespace and tablespace. (This
420  * should be true except when ALTER is deleting/recreating an index.)
421  * 'check_not_in_use': check for table not already in use in current session.
422  * This should be true unless caller is holding the table open, in which
423  * case the caller had better have checked it earlier.
424  * 'skip_build': make the catalog entries but don't create the index files
425  * 'quiet': suppress the NOTICE chatter ordinarily provided for constraints.
426  *
427  * Returns the object address of the created index.
428  */
430 DefineIndex(Oid relationId,
431  IndexStmt *stmt,
432  Oid indexRelationId,
433  Oid parentIndexId,
434  Oid parentConstraintId,
435  bool is_alter_table,
436  bool check_rights,
437  bool check_not_in_use,
438  bool skip_build,
439  bool quiet)
440 {
441  bool concurrent;
442  char *indexRelationName;
443  char *accessMethodName;
444  Oid *typeObjectId;
445  Oid *collationObjectId;
446  Oid *classObjectId;
447  Oid accessMethodId;
448  Oid namespaceId;
449  Oid tablespaceId;
450  Oid createdConstraintId = InvalidOid;
451  List *indexColNames;
452  List *allIndexParams;
453  Relation rel;
454  HeapTuple tuple;
455  Form_pg_am accessMethodForm;
456  IndexAmRoutine *amRoutine;
457  bool amcanorder;
458  amoptions_function amoptions;
459  bool partitioned;
460  Datum reloptions;
461  int16 *coloptions;
462  IndexInfo *indexInfo;
463  bits16 flags;
464  bits16 constr_flags;
465  int numberOfAttributes;
466  int numberOfKeyAttributes;
467  TransactionId limitXmin;
468  ObjectAddress address;
469  LockRelId heaprelid;
470  LOCKTAG heaplocktag;
471  LOCKMODE lockmode;
472  Snapshot snapshot;
473  int save_nestlevel = -1;
474  int i;
475 
476  /*
477  * Some callers need us to run with an empty default_tablespace; this is a
478  * necessary hack to be able to reproduce catalog state accurately when
479  * recreating indexes after table-rewriting ALTER TABLE.
480  */
481  if (stmt->reset_default_tblspc)
482  {
483  save_nestlevel = NewGUCNestLevel();
484  (void) set_config_option("default_tablespace", "",
486  GUC_ACTION_SAVE, true, 0, false);
487  }
488 
489  /*
490  * Force non-concurrent build on temporary relations, even if CONCURRENTLY
491  * was requested. Other backends can't access a temporary relation, so
492  * there's no harm in grabbing a stronger lock, and a non-concurrent DROP
493  * is more efficient. Do this before any use of the concurrent option is
494  * done.
495  */
496  if (stmt->concurrent && get_rel_persistence(relationId) != RELPERSISTENCE_TEMP)
497  concurrent = true;
498  else
499  concurrent = false;
500 
501  /*
502  * Start progress report. If we're building a partition, this was already
503  * done.
504  */
505  if (!OidIsValid(parentIndexId))
506  {
508  relationId);
510  concurrent ?
513  }
514 
515  /*
516  * No index OID to report yet
517  */
519  InvalidOid);
520 
521  /*
522  * count key attributes in index
523  */
524  numberOfKeyAttributes = list_length(stmt->indexParams);
525 
526  /*
527  * Calculate the new list of index columns including both key columns and
528  * INCLUDE columns. Later we can determine which of these are key
529  * columns, and which are just part of the INCLUDE list by checking the
530  * list position. A list item in a position less than ii_NumIndexKeyAttrs
531  * is part of the key columns, and anything equal to and over is part of
532  * the INCLUDE columns.
533  */
534  allIndexParams = list_concat_copy(stmt->indexParams,
535  stmt->indexIncludingParams);
536  numberOfAttributes = list_length(allIndexParams);
537 
538  if (numberOfAttributes <= 0)
539  ereport(ERROR,
540  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
541  errmsg("must specify at least one column")));
542  if (numberOfAttributes > INDEX_MAX_KEYS)
543  ereport(ERROR,
544  (errcode(ERRCODE_TOO_MANY_COLUMNS),
545  errmsg("cannot use more than %d columns in an index",
546  INDEX_MAX_KEYS)));
547 
548  /*
549  * Only SELECT ... FOR UPDATE/SHARE are allowed while doing a standard
550  * index build; but for concurrent builds we allow INSERT/UPDATE/DELETE
551  * (but not VACUUM).
552  *
553  * NB: Caller is responsible for making sure that relationId refers to the
554  * relation on which the index should be built; except in bootstrap mode,
555  * this will typically require the caller to have already locked the
556  * relation. To avoid lock upgrade hazards, that lock should be at least
557  * as strong as the one we take here.
558  *
559  * NB: If the lock strength here ever changes, code that is run by
560  * parallel workers under the control of certain particular ambuild
561  * functions will need to be updated, too.
562  */
563  lockmode = concurrent ? ShareUpdateExclusiveLock : ShareLock;
564  rel = table_open(relationId, lockmode);
565 
566  namespaceId = RelationGetNamespace(rel);
567 
568  /* Ensure that it makes sense to index this kind of relation */
569  switch (rel->rd_rel->relkind)
570  {
571  case RELKIND_RELATION:
572  case RELKIND_MATVIEW:
573  case RELKIND_PARTITIONED_TABLE:
574  /* OK */
575  break;
576  case RELKIND_FOREIGN_TABLE:
577 
578  /*
579  * Custom error message for FOREIGN TABLE since the term is close
580  * to a regular table and can confuse the user.
581  */
582  ereport(ERROR,
583  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
584  errmsg("cannot create index on foreign table \"%s\"",
585  RelationGetRelationName(rel))));
586  break;
587  default:
588  ereport(ERROR,
589  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
590  errmsg("\"%s\" is not a table or materialized view",
591  RelationGetRelationName(rel))));
592  break;
593  }
594 
595  /*
596  * Establish behavior for partitioned tables, and verify sanity of
597  * parameters.
598  *
599  * We do not build an actual index in this case; we only create a few
600  * catalog entries. The actual indexes are built by recursing for each
601  * partition.
602  */
603  partitioned = rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
604  if (partitioned)
605  {
606  /*
607  * Note: we check 'stmt->concurrent' rather than 'concurrent', so that
608  * the error is thrown also for temporary tables. Seems better to be
609  * consistent, even though we could do it on temporary table because
610  * we're not actually doing it concurrently.
611  */
612  if (stmt->concurrent)
613  ereport(ERROR,
614  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
615  errmsg("cannot create index on partitioned table \"%s\" concurrently",
616  RelationGetRelationName(rel))));
617  if (stmt->excludeOpNames)
618  ereport(ERROR,
619  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
620  errmsg("cannot create exclusion constraints on partitioned table \"%s\"",
621  RelationGetRelationName(rel))));
622  }
623 
624  /*
625  * Don't try to CREATE INDEX on temp tables of other backends.
626  */
627  if (RELATION_IS_OTHER_TEMP(rel))
628  ereport(ERROR,
629  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
630  errmsg("cannot create indexes on temporary tables of other sessions")));
631 
632  /*
633  * Unless our caller vouches for having checked this already, insist that
634  * the table not be in use by our own session, either. Otherwise we might
635  * fail to make entries in the new index (for instance, if an INSERT or
636  * UPDATE is in progress and has already made its list of target indexes).
637  */
638  if (check_not_in_use)
639  CheckTableNotInUse(rel, "CREATE INDEX");
640 
641  /*
642  * Verify we (still) have CREATE rights in the rel's namespace.
643  * (Presumably we did when the rel was created, but maybe not anymore.)
644  * Skip check if caller doesn't want it. Also skip check if
645  * bootstrapping, since permissions machinery may not be working yet.
646  */
647  if (check_rights && !IsBootstrapProcessingMode())
648  {
649  AclResult aclresult;
650 
651  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
652  ACL_CREATE);
653  if (aclresult != ACLCHECK_OK)
654  aclcheck_error(aclresult, OBJECT_SCHEMA,
655  get_namespace_name(namespaceId));
656  }
657 
658  /*
659  * Select tablespace to use. If not specified, use default tablespace
660  * (which may in turn default to database's default).
661  */
662  if (stmt->tableSpace)
663  {
664  tablespaceId = get_tablespace_oid(stmt->tableSpace, false);
665  if (partitioned && tablespaceId == MyDatabaseTableSpace)
666  ereport(ERROR,
667  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
668  errmsg("cannot specify default tablespace for partitioned relations")));
669  }
670  else
671  {
672  tablespaceId = GetDefaultTablespace(rel->rd_rel->relpersistence,
673  partitioned);
674  /* note InvalidOid is OK in this case */
675  }
676 
677  /* Check tablespace permissions */
678  if (check_rights &&
679  OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
680  {
681  AclResult aclresult;
682 
683  aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
684  ACL_CREATE);
685  if (aclresult != ACLCHECK_OK)
687  get_tablespace_name(tablespaceId));
688  }
689 
690  /*
691  * Force shared indexes into the pg_global tablespace. This is a bit of a
692  * hack but seems simpler than marking them in the BKI commands. On the
693  * other hand, if it's not shared, don't allow it to be placed there.
694  */
695  if (rel->rd_rel->relisshared)
696  tablespaceId = GLOBALTABLESPACE_OID;
697  else if (tablespaceId == GLOBALTABLESPACE_OID)
698  ereport(ERROR,
699  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
700  errmsg("only shared relations can be placed in pg_global tablespace")));
701 
702  /*
703  * Choose the index column names.
704  */
705  indexColNames = ChooseIndexColumnNames(allIndexParams);
706 
707  /*
708  * Select name for index if caller didn't specify
709  */
710  indexRelationName = stmt->idxname;
711  if (indexRelationName == NULL)
712  indexRelationName = ChooseIndexName(RelationGetRelationName(rel),
713  namespaceId,
714  indexColNames,
715  stmt->excludeOpNames,
716  stmt->primary,
717  stmt->isconstraint);
718 
719  /*
720  * look up the access method, verify it can handle the requested features
721  */
722  accessMethodName = stmt->accessMethod;
723  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
724  if (!HeapTupleIsValid(tuple))
725  {
726  /*
727  * Hack to provide more-or-less-transparent updating of old RTREE
728  * indexes to GiST: if RTREE is requested and not found, use GIST.
729  */
730  if (strcmp(accessMethodName, "rtree") == 0)
731  {
732  ereport(NOTICE,
733  (errmsg("substituting access method \"gist\" for obsolete method \"rtree\"")));
734  accessMethodName = "gist";
735  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
736  }
737 
738  if (!HeapTupleIsValid(tuple))
739  ereport(ERROR,
740  (errcode(ERRCODE_UNDEFINED_OBJECT),
741  errmsg("access method \"%s\" does not exist",
742  accessMethodName)));
743  }
744  accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
745  accessMethodId = accessMethodForm->oid;
746  amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
747 
749  accessMethodId);
750 
751  if (stmt->unique && !amRoutine->amcanunique)
752  ereport(ERROR,
753  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
754  errmsg("access method \"%s\" does not support unique indexes",
755  accessMethodName)));
756  if (stmt->indexIncludingParams != NIL && !amRoutine->amcaninclude)
757  ereport(ERROR,
758  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
759  errmsg("access method \"%s\" does not support included columns",
760  accessMethodName)));
761  if (numberOfAttributes > 1 && !amRoutine->amcanmulticol)
762  ereport(ERROR,
763  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
764  errmsg("access method \"%s\" does not support multicolumn indexes",
765  accessMethodName)));
766  if (stmt->excludeOpNames && amRoutine->amgettuple == NULL)
767  ereport(ERROR,
768  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
769  errmsg("access method \"%s\" does not support exclusion constraints",
770  accessMethodName)));
771 
772  amcanorder = amRoutine->amcanorder;
773  amoptions = amRoutine->amoptions;
774 
775  pfree(amRoutine);
776  ReleaseSysCache(tuple);
777 
778  /*
779  * Validate predicate, if given
780  */
781  if (stmt->whereClause)
782  CheckPredicate((Expr *) stmt->whereClause);
783 
784  /*
785  * Parse AM-specific options, convert to text array form, validate.
786  */
787  reloptions = transformRelOptions((Datum) 0, stmt->options,
788  NULL, NULL, false, false);
789 
790  (void) index_reloptions(amoptions, reloptions, true);
791 
792  /*
793  * Prepare arguments for index_create, primarily an IndexInfo structure.
794  * Note that predicates must be in implicit-AND format. In a concurrent
795  * build, mark it not-ready-for-inserts.
796  */
797  indexInfo = makeIndexInfo(numberOfAttributes,
798  numberOfKeyAttributes,
799  accessMethodId,
800  NIL, /* expressions, NIL for now */
802  stmt->unique,
803  !concurrent,
804  concurrent);
805 
806  typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
807  collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
808  classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
809  coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16));
810  ComputeIndexAttrs(indexInfo,
811  typeObjectId, collationObjectId, classObjectId,
812  coloptions, allIndexParams,
813  stmt->excludeOpNames, relationId,
814  accessMethodName, accessMethodId,
815  amcanorder, stmt->isconstraint);
816 
817  /*
818  * Extra checks when creating a PRIMARY KEY index.
819  */
820  if (stmt->primary)
821  index_check_primary_key(rel, indexInfo, is_alter_table, stmt);
822 
823  /*
824  * If this table is partitioned and we're creating a unique index or a
825  * primary key, make sure that the indexed columns are part of the
826  * partition key. Otherwise it would be possible to violate uniqueness by
827  * putting values that ought to be unique in different partitions.
828  *
829  * We could lift this limitation if we had global indexes, but those have
830  * their own problems, so this is a useful feature combination.
831  */
832  if (partitioned && (stmt->unique || stmt->primary))
833  {
835  int i;
836 
837  /*
838  * A partitioned table can have unique indexes, as long as all the
839  * columns in the partition key appear in the unique key. A
840  * partition-local index can enforce global uniqueness iff the PK
841  * value completely determines the partition that a row is in.
842  *
843  * Thus, verify that all the columns in the partition key appear in
844  * the unique key definition.
845  */
846  for (i = 0; i < key->partnatts; i++)
847  {
848  bool found = false;
849  int j;
850  const char *constraint_type;
851 
852  if (stmt->primary)
853  constraint_type = "PRIMARY KEY";
854  else if (stmt->unique)
855  constraint_type = "UNIQUE";
856  else if (stmt->excludeOpNames != NIL)
857  constraint_type = "EXCLUDE";
858  else
859  {
860  elog(ERROR, "unknown constraint type");
861  constraint_type = NULL; /* keep compiler quiet */
862  }
863 
864  /*
865  * It may be possible to support UNIQUE constraints when partition
866  * keys are expressions, but is it worth it? Give up for now.
867  */
868  if (key->partattrs[i] == 0)
869  ereport(ERROR,
870  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
871  errmsg("unsupported %s constraint with partition key definition",
872  constraint_type),
873  errdetail("%s constraints cannot be used when partition keys include expressions.",
874  constraint_type)));
875 
876  for (j = 0; j < indexInfo->ii_NumIndexKeyAttrs; j++)
877  {
878  if (key->partattrs[i] == indexInfo->ii_IndexAttrNumbers[j])
879  {
880  found = true;
881  break;
882  }
883  }
884  if (!found)
885  {
886  Form_pg_attribute att;
887 
888  att = TupleDescAttr(RelationGetDescr(rel), key->partattrs[i] - 1);
889  ereport(ERROR,
890  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
891  errmsg("insufficient columns in %s constraint definition",
892  constraint_type),
893  errdetail("%s constraint on table \"%s\" lacks column \"%s\" which is part of the partition key.",
894  constraint_type, RelationGetRelationName(rel),
895  NameStr(att->attname))));
896  }
897  }
898  }
899 
900 
901  /*
902  * We disallow indexes on system columns. They would not necessarily get
903  * updated correctly, and they don't seem useful anyway.
904  */
905  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
906  {
907  AttrNumber attno = indexInfo->ii_IndexAttrNumbers[i];
908 
909  if (attno < 0)
910  ereport(ERROR,
911  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
912  errmsg("index creation on system columns is not supported")));
913  }
914 
915  /*
916  * Also check for system columns used in expressions or predicates.
917  */
918  if (indexInfo->ii_Expressions || indexInfo->ii_Predicate)
919  {
920  Bitmapset *indexattrs = NULL;
921 
922  pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs);
923  pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs);
924 
925  for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
926  {
928  indexattrs))
929  ereport(ERROR,
930  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
931  errmsg("index creation on system columns is not supported")));
932  }
933  }
934 
935  /*
936  * Report index creation if appropriate (delay this till after most of the
937  * error checks)
938  */
939  if (stmt->isconstraint && !quiet)
940  {
941  const char *constraint_type;
942 
943  if (stmt->primary)
944  constraint_type = "PRIMARY KEY";
945  else if (stmt->unique)
946  constraint_type = "UNIQUE";
947  else if (stmt->excludeOpNames != NIL)
948  constraint_type = "EXCLUDE";
949  else
950  {
951  elog(ERROR, "unknown constraint type");
952  constraint_type = NULL; /* keep compiler quiet */
953  }
954 
955  ereport(DEBUG1,
956  (errmsg("%s %s will create implicit index \"%s\" for table \"%s\"",
957  is_alter_table ? "ALTER TABLE / ADD" : "CREATE TABLE /",
958  constraint_type,
959  indexRelationName, RelationGetRelationName(rel))));
960  }
961 
962  /*
963  * A valid stmt->oldNode implies that we already have a built form of the
964  * index. The caller should also decline any index build.
965  */
966  Assert(!OidIsValid(stmt->oldNode) || (skip_build && !concurrent));
967 
968  /*
969  * Make the catalog entries for the index, including constraints. This
970  * step also actually builds the index, except if caller requested not to
971  * or in concurrent mode, in which case it'll be done later, or doing a
972  * partitioned index (because those don't have storage).
973  */
974  flags = constr_flags = 0;
975  if (stmt->isconstraint)
977  if (skip_build || concurrent || partitioned)
978  flags |= INDEX_CREATE_SKIP_BUILD;
979  if (stmt->if_not_exists)
981  if (concurrent)
982  flags |= INDEX_CREATE_CONCURRENT;
983  if (partitioned)
984  flags |= INDEX_CREATE_PARTITIONED;
985  if (stmt->primary)
986  flags |= INDEX_CREATE_IS_PRIMARY;
987 
988  /*
989  * If the table is partitioned, and recursion was declined but partitions
990  * exist, mark the index as invalid.
991  */
992  if (partitioned && stmt->relation && !stmt->relation->inh)
993  {
995 
996  if (pd->nparts != 0)
997  flags |= INDEX_CREATE_INVALID;
998  }
999 
1000  if (stmt->deferrable)
1001  constr_flags |= INDEX_CONSTR_CREATE_DEFERRABLE;
1002  if (stmt->initdeferred)
1003  constr_flags |= INDEX_CONSTR_CREATE_INIT_DEFERRED;
1004 
1005  indexRelationId =
1006  index_create(rel, indexRelationName, indexRelationId, parentIndexId,
1007  parentConstraintId,
1008  stmt->oldNode, indexInfo, indexColNames,
1009  accessMethodId, tablespaceId,
1010  collationObjectId, classObjectId,
1011  coloptions, reloptions,
1012  flags, constr_flags,
1013  allowSystemTableMods, !check_rights,
1014  &createdConstraintId);
1015 
1016  ObjectAddressSet(address, RelationRelationId, indexRelationId);
1017 
1018  /*
1019  * Revert to original default_tablespace. Must do this before any return
1020  * from this function, but after index_create, so this is a good time.
1021  */
1022  if (save_nestlevel >= 0)
1023  AtEOXact_GUC(true, save_nestlevel);
1024 
1025  if (!OidIsValid(indexRelationId))
1026  {
1027  table_close(rel, NoLock);
1028 
1029  /* If this is the top-level index, we're done */
1030  if (!OidIsValid(parentIndexId))
1032 
1033  return address;
1034  }
1035 
1036  /* Add any requested comment */
1037  if (stmt->idxcomment != NULL)
1038  CreateComments(indexRelationId, RelationRelationId, 0,
1039  stmt->idxcomment);
1040 
1041  if (partitioned)
1042  {
1043  /*
1044  * Unless caller specified to skip this step (via ONLY), process each
1045  * partition to make sure they all contain a corresponding index.
1046  *
1047  * If we're called internally (no stmt->relation), recurse always.
1048  */
1049  if (!stmt->relation || stmt->relation->inh)
1050  {
1051  PartitionDesc partdesc = RelationGetPartitionDesc(rel);
1052  int nparts = partdesc->nparts;
1053  Oid *part_oids = palloc(sizeof(Oid) * nparts);
1054  bool invalidate_parent = false;
1055  TupleDesc parentDesc;
1056  Oid *opfamOids;
1057 
1059  nparts);
1060 
1061  memcpy(part_oids, partdesc->oids, sizeof(Oid) * nparts);
1062 
1063  parentDesc = RelationGetDescr(rel);
1064  opfamOids = palloc(sizeof(Oid) * numberOfKeyAttributes);
1065  for (i = 0; i < numberOfKeyAttributes; i++)
1066  opfamOids[i] = get_opclass_family(classObjectId[i]);
1067 
1068  /*
1069  * For each partition, scan all existing indexes; if one matches
1070  * our index definition and is not already attached to some other
1071  * parent index, attach it to the one we just created.
1072  *
1073  * If none matches, build a new index by calling ourselves
1074  * recursively with the same options (except for the index name).
1075  */
1076  for (i = 0; i < nparts; i++)
1077  {
1078  Oid childRelid = part_oids[i];
1079  Relation childrel;
1080  List *childidxs;
1081  ListCell *cell;
1082  AttrMap *attmap;
1083  bool found = false;
1084 
1085  childrel = table_open(childRelid, lockmode);
1086 
1087  /*
1088  * Don't try to create indexes on foreign tables, though. Skip
1089  * those if a regular index, or fail if trying to create a
1090  * constraint index.
1091  */
1092  if (childrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1093  {
1094  if (stmt->unique || stmt->primary)
1095  ereport(ERROR,
1096  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1097  errmsg("cannot create unique index on partitioned table \"%s\"",
1099  errdetail("Table \"%s\" contains partitions that are foreign tables.",
1100  RelationGetRelationName(rel))));
1101 
1102  table_close(childrel, lockmode);
1103  continue;
1104  }
1105 
1106  childidxs = RelationGetIndexList(childrel);
1107  attmap =
1109  parentDesc);
1110 
1111  foreach(cell, childidxs)
1112  {
1113  Oid cldidxid = lfirst_oid(cell);
1114  Relation cldidx;
1115  IndexInfo *cldIdxInfo;
1116 
1117  /* this index is already partition of another one */
1118  if (has_superclass(cldidxid))
1119  continue;
1120 
1121  cldidx = index_open(cldidxid, lockmode);
1122  cldIdxInfo = BuildIndexInfo(cldidx);
1123  if (CompareIndexInfo(cldIdxInfo, indexInfo,
1124  cldidx->rd_indcollation,
1125  collationObjectId,
1126  cldidx->rd_opfamily,
1127  opfamOids,
1128  attmap))
1129  {
1130  Oid cldConstrOid = InvalidOid;
1131 
1132  /*
1133  * Found a match.
1134  *
1135  * If this index is being created in the parent
1136  * because of a constraint, then the child needs to
1137  * have a constraint also, so look for one. If there
1138  * is no such constraint, this index is no good, so
1139  * keep looking.
1140  */
1141  if (createdConstraintId != InvalidOid)
1142  {
1143  cldConstrOid =
1145  cldidxid);
1146  if (cldConstrOid == InvalidOid)
1147  {
1148  index_close(cldidx, lockmode);
1149  continue;
1150  }
1151  }
1152 
1153  /* Attach index to parent and we're done. */
1154  IndexSetParentIndex(cldidx, indexRelationId);
1155  if (createdConstraintId != InvalidOid)
1156  ConstraintSetParentConstraint(cldConstrOid,
1157  createdConstraintId,
1158  childRelid);
1159 
1160  if (!cldidx->rd_index->indisvalid)
1161  invalidate_parent = true;
1162 
1163  found = true;
1164  /* keep lock till commit */
1165  index_close(cldidx, NoLock);
1166  break;
1167  }
1168 
1169  index_close(cldidx, lockmode);
1170  }
1171 
1172  list_free(childidxs);
1173  table_close(childrel, NoLock);
1174 
1175  /*
1176  * If no matching index was found, create our own.
1177  */
1178  if (!found)
1179  {
1180  IndexStmt *childStmt = copyObject(stmt);
1181  bool found_whole_row;
1182  ListCell *lc;
1183 
1184  /*
1185  * We can't use the same index name for the child index,
1186  * so clear idxname to let the recursive invocation choose
1187  * a new name. Likewise, the existing target relation
1188  * field is wrong, and if indexOid or oldNode are set,
1189  * they mustn't be applied to the child either.
1190  */
1191  childStmt->idxname = NULL;
1192  childStmt->relation = NULL;
1193  childStmt->indexOid = InvalidOid;
1194  childStmt->oldNode = InvalidOid;
1195 
1196  /*
1197  * Adjust any Vars (both in expressions and in the index's
1198  * WHERE clause) to match the partition's column numbering
1199  * in case it's different from the parent's.
1200  */
1201  foreach(lc, childStmt->indexParams)
1202  {
1203  IndexElem *ielem = lfirst(lc);
1204 
1205  /*
1206  * If the index parameter is an expression, we must
1207  * translate it to contain child Vars.
1208  */
1209  if (ielem->expr)
1210  {
1211  ielem->expr =
1212  map_variable_attnos((Node *) ielem->expr,
1213  1, 0, attmap,
1214  InvalidOid,
1215  &found_whole_row);
1216  if (found_whole_row)
1217  elog(ERROR, "cannot convert whole-row table reference");
1218  }
1219  }
1220  childStmt->whereClause =
1221  map_variable_attnos(stmt->whereClause, 1, 0,
1222  attmap,
1223  InvalidOid, &found_whole_row);
1224  if (found_whole_row)
1225  elog(ERROR, "cannot convert whole-row table reference");
1226 
1227  DefineIndex(childRelid, childStmt,
1228  InvalidOid, /* no predefined OID */
1229  indexRelationId, /* this is our child */
1230  createdConstraintId,
1231  is_alter_table, check_rights, check_not_in_use,
1232  skip_build, quiet);
1233  }
1234 
1236  i + 1);
1237  free_attrmap(attmap);
1238  }
1239 
1240  /*
1241  * The pg_index row we inserted for this index was marked
1242  * indisvalid=true. But if we attached an existing index that is
1243  * invalid, this is incorrect, so update our row to invalid too.
1244  */
1245  if (invalidate_parent)
1246  {
1247  Relation pg_index = table_open(IndexRelationId, RowExclusiveLock);
1248  HeapTuple tup,
1249  newtup;
1250 
1252  ObjectIdGetDatum(indexRelationId));
1253  if (!HeapTupleIsValid(tup))
1254  elog(ERROR, "cache lookup failed for index %u",
1255  indexRelationId);
1256  newtup = heap_copytuple(tup);
1257  ((Form_pg_index) GETSTRUCT(newtup))->indisvalid = false;
1258  CatalogTupleUpdate(pg_index, &tup->t_self, newtup);
1259  ReleaseSysCache(tup);
1260  table_close(pg_index, RowExclusiveLock);
1261  heap_freetuple(newtup);
1262  }
1263  }
1264 
1265  /*
1266  * Indexes on partitioned tables are not themselves built, so we're
1267  * done here.
1268  */
1269  table_close(rel, NoLock);
1270  if (!OidIsValid(parentIndexId))
1272  return address;
1273  }
1274 
1275  if (!concurrent)
1276  {
1277  /* Close the heap and we're done, in the non-concurrent case */
1278  table_close(rel, NoLock);
1279 
1280  /* If this is the top-level index, we're done. */
1281  if (!OidIsValid(parentIndexId))
1283 
1284  return address;
1285  }
1286 
1287  /* save lockrelid and locktag for below, then close rel */
1288  heaprelid = rel->rd_lockInfo.lockRelId;
1289  SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
1290  table_close(rel, NoLock);
1291 
1292  /*
1293  * For a concurrent build, it's important to make the catalog entries
1294  * visible to other transactions before we start to build the index. That
1295  * will prevent them from making incompatible HOT updates. The new index
1296  * will be marked not indisready and not indisvalid, so that no one else
1297  * tries to either insert into it or use it for queries.
1298  *
1299  * We must commit our current transaction so that the index becomes
1300  * visible; then start another. Note that all the data structures we just
1301  * built are lost in the commit. The only data we keep past here are the
1302  * relation IDs.
1303  *
1304  * Before committing, get a session-level lock on the table, to ensure
1305  * that neither it nor the index can be dropped before we finish. This
1306  * cannot block, even if someone else is waiting for access, because we
1307  * already have the same lock within our transaction.
1308  *
1309  * Note: we don't currently bother with a session lock on the index,
1310  * because there are no operations that could change its state while we
1311  * hold lock on the parent table. This might need to change later.
1312  */
1314 
1318 
1319  /*
1320  * The index is now visible, so we can report the OID.
1321  */
1323  indexRelationId);
1324 
1325  /*
1326  * Phase 2 of concurrent index build (see comments for validate_index()
1327  * for an overview of how this works)
1328  *
1329  * Now we must wait until no running transaction could have the table open
1330  * with the old list of indexes. Use ShareLock to consider running
1331  * transactions that hold locks that permit writing to the table. Note we
1332  * do not need to worry about xacts that open the table for writing after
1333  * this point; they will see the new index when they open it.
1334  *
1335  * Note: the reason we use actual lock acquisition here, rather than just
1336  * checking the ProcArray and sleeping, is that deadlock is possible if
1337  * one of the transactions in question is blocked trying to acquire an
1338  * exclusive lock on our table. The lock code will detect deadlock and
1339  * error out properly.
1340  */
1343  WaitForLockers(heaplocktag, ShareLock, true);
1344 
1345  /*
1346  * At this moment we are sure that there are no transactions with the
1347  * table open for write that don't have this new index in their list of
1348  * indexes. We have waited out all the existing transactions and any new
1349  * transaction will have the new index in its list, but the index is still
1350  * marked as "not-ready-for-inserts". The index is consulted while
1351  * deciding HOT-safety though. This arrangement ensures that no new HOT
1352  * chains can be created where the new tuple and the old tuple in the
1353  * chain have different index keys.
1354  *
1355  * We now take a new snapshot, and build the index using all tuples that
1356  * are visible in this snapshot. We can be sure that any HOT updates to
1357  * these tuples will be compatible with the index, since any updates made
1358  * by transactions that didn't know about the index are now committed or
1359  * rolled back. Thus, each visible tuple is either the end of its
1360  * HOT-chain or the extension of the chain is HOT-safe for this index.
1361  */
1362 
1363  /* Set ActiveSnapshot since functions in the indexes may need it */
1365 
1366  /* Perform concurrent build of index */
1367  index_concurrently_build(relationId, indexRelationId);
1368 
1369  /* we can do away with our snapshot */
1371 
1372  /*
1373  * Commit this transaction to make the indisready update visible.
1374  */
1377 
1378  /*
1379  * Phase 3 of concurrent index build
1380  *
1381  * We once again wait until no transaction can have the table open with
1382  * the index marked as read-only for updates.
1383  */
1386  WaitForLockers(heaplocktag, ShareLock, true);
1387 
1388  /*
1389  * Now take the "reference snapshot" that will be used by validate_index()
1390  * to filter candidate tuples. Beware! There might still be snapshots in
1391  * use that treat some transaction as in-progress that our reference
1392  * snapshot treats as committed. If such a recently-committed transaction
1393  * deleted tuples in the table, we will not include them in the index; yet
1394  * those transactions which see the deleting one as still-in-progress will
1395  * expect such tuples to be there once we mark the index as valid.
1396  *
1397  * We solve this by waiting for all endangered transactions to exit before
1398  * we mark the index as valid.
1399  *
1400  * We also set ActiveSnapshot to this snap, since functions in indexes may
1401  * need a snapshot.
1402  */
1404  PushActiveSnapshot(snapshot);
1405 
1406  /*
1407  * Scan the index and the heap, insert any missing index entries.
1408  */
1409  validate_index(relationId, indexRelationId, snapshot);
1410 
1411  /*
1412  * Drop the reference snapshot. We must do this before waiting out other
1413  * snapshot holders, else we will deadlock against other processes also
1414  * doing CREATE INDEX CONCURRENTLY, which would see our snapshot as one
1415  * they must wait for. But first, save the snapshot's xmin to use as
1416  * limitXmin for GetCurrentVirtualXIDs().
1417  */
1418  limitXmin = snapshot->xmin;
1419 
1421  UnregisterSnapshot(snapshot);
1422 
1423  /*
1424  * The snapshot subsystem could still contain registered snapshots that
1425  * are holding back our process's advertised xmin; in particular, if
1426  * default_transaction_isolation = serializable, there is a transaction
1427  * snapshot that is still active. The CatalogSnapshot is likewise a
1428  * hazard. To ensure no deadlocks, we must commit and start yet another
1429  * transaction, and do our wait before any snapshot has been taken in it.
1430  */
1433 
1434  /* We should now definitely not be advertising any xmin. */
1436 
1437  /*
1438  * The index is now valid in the sense that it contains all currently
1439  * interesting tuples. But since it might not contain tuples deleted just
1440  * before the reference snap was taken, we have to wait out any
1441  * transactions that might have older snapshots.
1442  */
1445  WaitForOlderSnapshots(limitXmin, true);
1446 
1447  /*
1448  * Index can now be marked valid -- update its pg_index entry
1449  */
1451 
1452  /*
1453  * The pg_index update will cause backends (including this one) to update
1454  * relcache entries for the index itself, but we should also send a
1455  * relcache inval on the parent table to force replanning of cached plans.
1456  * Otherwise existing sessions might fail to use the new index where it
1457  * would be useful. (Note that our earlier commits did not create reasons
1458  * to replan; so relcache flush on the index itself was sufficient.)
1459  */
1461 
1462  /*
1463  * Last thing to do is release the session-level lock on the parent table.
1464  */
1466 
1468 
1469  return address;
1470 }
1471 
1472 
1473 /*
1474  * CheckMutability
1475  * Test whether given expression is mutable
1476  */
1477 static bool
1479 {
1480  /*
1481  * First run the expression through the planner. This has a couple of
1482  * important consequences. First, function default arguments will get
1483  * inserted, which may affect volatility (consider "default now()").
1484  * Second, inline-able functions will get inlined, which may allow us to
1485  * conclude that the function is really less volatile than it's marked. As
1486  * an example, polymorphic functions must be marked with the most volatile
1487  * behavior that they have for any input type, but once we inline the
1488  * function we may be able to conclude that it's not so volatile for the
1489  * particular input type we're dealing with.
1490  *
1491  * We assume here that expression_planner() won't scribble on its input.
1492  */
1493  expr = expression_planner(expr);
1494 
1495  /* Now we can search for non-immutable functions */
1496  return contain_mutable_functions((Node *) expr);
1497 }
1498 
1499 
1500 /*
1501  * CheckPredicate
1502  * Checks that the given partial-index predicate is valid.
1503  *
1504  * This used to also constrain the form of the predicate to forms that
1505  * indxpath.c could do something with. However, that seems overly
1506  * restrictive. One useful application of partial indexes is to apply
1507  * a UNIQUE constraint across a subset of a table, and in that scenario
1508  * any evaluable predicate will work. So accept any predicate here
1509  * (except ones requiring a plan), and let indxpath.c fend for itself.
1510  */
1511 static void
1513 {
1514  /*
1515  * transformExpr() should have already rejected subqueries, aggregates,
1516  * and window functions, based on the EXPR_KIND_ for a predicate.
1517  */
1518 
1519  /*
1520  * A predicate using mutable functions is probably wrong, for the same
1521  * reasons that we don't allow an index expression to use one.
1522  */
1523  if (CheckMutability(predicate))
1524  ereport(ERROR,
1525  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1526  errmsg("functions in index predicate must be marked IMMUTABLE")));
1527 }
1528 
1529 /*
1530  * Compute per-index-column information, including indexed column numbers
1531  * or index expressions, opclasses, and indoptions. Note, all output vectors
1532  * should be allocated for all columns, including "including" ones.
1533  */
1534 static void
1536  Oid *typeOidP,
1537  Oid *collationOidP,
1538  Oid *classOidP,
1539  int16 *colOptionP,
1540  List *attList, /* list of IndexElem's */
1541  List *exclusionOpNames,
1542  Oid relId,
1543  const char *accessMethodName,
1544  Oid accessMethodId,
1545  bool amcanorder,
1546  bool isconstraint)
1547 {
1548  ListCell *nextExclOp;
1549  ListCell *lc;
1550  int attn;
1551  int nkeycols = indexInfo->ii_NumIndexKeyAttrs;
1552 
1553  /* Allocate space for exclusion operator info, if needed */
1554  if (exclusionOpNames)
1555  {
1556  Assert(list_length(exclusionOpNames) == nkeycols);
1557  indexInfo->ii_ExclusionOps = (Oid *) palloc(sizeof(Oid) * nkeycols);
1558  indexInfo->ii_ExclusionProcs = (Oid *) palloc(sizeof(Oid) * nkeycols);
1559  indexInfo->ii_ExclusionStrats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
1560  nextExclOp = list_head(exclusionOpNames);
1561  }
1562  else
1563  nextExclOp = NULL;
1564 
1565  /*
1566  * process attributeList
1567  */
1568  attn = 0;
1569  foreach(lc, attList)
1570  {
1571  IndexElem *attribute = (IndexElem *) lfirst(lc);
1572  Oid atttype;
1573  Oid attcollation;
1574 
1575  /*
1576  * Process the column-or-expression to be indexed.
1577  */
1578  if (attribute->name != NULL)
1579  {
1580  /* Simple index attribute */
1581  HeapTuple atttuple;
1582  Form_pg_attribute attform;
1583 
1584  Assert(attribute->expr == NULL);
1585  atttuple = SearchSysCacheAttName(relId, attribute->name);
1586  if (!HeapTupleIsValid(atttuple))
1587  {
1588  /* difference in error message spellings is historical */
1589  if (isconstraint)
1590  ereport(ERROR,
1591  (errcode(ERRCODE_UNDEFINED_COLUMN),
1592  errmsg("column \"%s\" named in key does not exist",
1593  attribute->name)));
1594  else
1595  ereport(ERROR,
1596  (errcode(ERRCODE_UNDEFINED_COLUMN),
1597  errmsg("column \"%s\" does not exist",
1598  attribute->name)));
1599  }
1600  attform = (Form_pg_attribute) GETSTRUCT(atttuple);
1601  indexInfo->ii_IndexAttrNumbers[attn] = attform->attnum;
1602  atttype = attform->atttypid;
1603  attcollation = attform->attcollation;
1604  ReleaseSysCache(atttuple);
1605  }
1606  else
1607  {
1608  /* Index expression */
1609  Node *expr = attribute->expr;
1610 
1611  Assert(expr != NULL);
1612 
1613  if (attn >= nkeycols)
1614  ereport(ERROR,
1615  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1616  errmsg("expressions are not supported in included columns")));
1617  atttype = exprType(expr);
1618  attcollation = exprCollation(expr);
1619 
1620  /*
1621  * Strip any top-level COLLATE clause. This ensures that we treat
1622  * "x COLLATE y" and "(x COLLATE y)" alike.
1623  */
1624  while (IsA(expr, CollateExpr))
1625  expr = (Node *) ((CollateExpr *) expr)->arg;
1626 
1627  if (IsA(expr, Var) &&
1628  ((Var *) expr)->varattno != InvalidAttrNumber)
1629  {
1630  /*
1631  * User wrote "(column)" or "(column COLLATE something)".
1632  * Treat it like simple attribute anyway.
1633  */
1634  indexInfo->ii_IndexAttrNumbers[attn] = ((Var *) expr)->varattno;
1635  }
1636  else
1637  {
1638  indexInfo->ii_IndexAttrNumbers[attn] = 0; /* marks expression */
1639  indexInfo->ii_Expressions = lappend(indexInfo->ii_Expressions,
1640  expr);
1641 
1642  /*
1643  * transformExpr() should have already rejected subqueries,
1644  * aggregates, and window functions, based on the EXPR_KIND_
1645  * for an index expression.
1646  */
1647 
1648  /*
1649  * An expression using mutable functions is probably wrong,
1650  * since if you aren't going to get the same result for the
1651  * same data every time, it's not clear what the index entries
1652  * mean at all.
1653  */
1654  if (CheckMutability((Expr *) expr))
1655  ereport(ERROR,
1656  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1657  errmsg("functions in index expression must be marked IMMUTABLE")));
1658  }
1659  }
1660 
1661  typeOidP[attn] = atttype;
1662 
1663  /*
1664  * Included columns have no collation, no opclass and no ordering
1665  * options.
1666  */
1667  if (attn >= nkeycols)
1668  {
1669  if (attribute->collation)
1670  ereport(ERROR,
1671  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1672  errmsg("including column does not support a collation")));
1673  if (attribute->opclass)
1674  ereport(ERROR,
1675  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1676  errmsg("including column does not support an operator class")));
1677  if (attribute->ordering != SORTBY_DEFAULT)
1678  ereport(ERROR,
1679  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1680  errmsg("including column does not support ASC/DESC options")));
1681  if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
1682  ereport(ERROR,
1683  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1684  errmsg("including column does not support NULLS FIRST/LAST options")));
1685 
1686  classOidP[attn] = InvalidOid;
1687  colOptionP[attn] = 0;
1688  collationOidP[attn] = InvalidOid;
1689  attn++;
1690 
1691  continue;
1692  }
1693 
1694  /*
1695  * Apply collation override if any
1696  */
1697  if (attribute->collation)
1698  attcollation = get_collation_oid(attribute->collation, false);
1699 
1700  /*
1701  * Check we have a collation iff it's a collatable type. The only
1702  * expected failures here are (1) COLLATE applied to a noncollatable
1703  * type, or (2) index expression had an unresolved collation. But we
1704  * might as well code this to be a complete consistency check.
1705  */
1706  if (type_is_collatable(atttype))
1707  {
1708  if (!OidIsValid(attcollation))
1709  ereport(ERROR,
1710  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1711  errmsg("could not determine which collation to use for index expression"),
1712  errhint("Use the COLLATE clause to set the collation explicitly.")));
1713  }
1714  else
1715  {
1716  if (OidIsValid(attcollation))
1717  ereport(ERROR,
1718  (errcode(ERRCODE_DATATYPE_MISMATCH),
1719  errmsg("collations are not supported by type %s",
1720  format_type_be(atttype))));
1721  }
1722 
1723  collationOidP[attn] = attcollation;
1724 
1725  /*
1726  * Identify the opclass to use.
1727  */
1728  classOidP[attn] = ResolveOpClass(attribute->opclass,
1729  atttype,
1730  accessMethodName,
1731  accessMethodId);
1732 
1733  /*
1734  * Identify the exclusion operator, if any.
1735  */
1736  if (nextExclOp)
1737  {
1738  List *opname = (List *) lfirst(nextExclOp);
1739  Oid opid;
1740  Oid opfamily;
1741  int strat;
1742 
1743  /*
1744  * Find the operator --- it must accept the column datatype
1745  * without runtime coercion (but binary compatibility is OK)
1746  */
1747  opid = compatible_oper_opid(opname, atttype, atttype, false);
1748 
1749  /*
1750  * Only allow commutative operators to be used in exclusion
1751  * constraints. If X conflicts with Y, but Y does not conflict
1752  * with X, bad things will happen.
1753  */
1754  if (get_commutator(opid) != opid)
1755  ereport(ERROR,
1756  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1757  errmsg("operator %s is not commutative",
1758  format_operator(opid)),
1759  errdetail("Only commutative operators can be used in exclusion constraints.")));
1760 
1761  /*
1762  * Operator must be a member of the right opfamily, too
1763  */
1764  opfamily = get_opclass_family(classOidP[attn]);
1765  strat = get_op_opfamily_strategy(opid, opfamily);
1766  if (strat == 0)
1767  {
1768  HeapTuple opftuple;
1769  Form_pg_opfamily opfform;
1770 
1771  /*
1772  * attribute->opclass might not explicitly name the opfamily,
1773  * so fetch the name of the selected opfamily for use in the
1774  * error message.
1775  */
1776  opftuple = SearchSysCache1(OPFAMILYOID,
1777  ObjectIdGetDatum(opfamily));
1778  if (!HeapTupleIsValid(opftuple))
1779  elog(ERROR, "cache lookup failed for opfamily %u",
1780  opfamily);
1781  opfform = (Form_pg_opfamily) GETSTRUCT(opftuple);
1782 
1783  ereport(ERROR,
1784  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1785  errmsg("operator %s is not a member of operator family \"%s\"",
1786  format_operator(opid),
1787  NameStr(opfform->opfname)),
1788  errdetail("The exclusion operator must be related to the index operator class for the constraint.")));
1789  }
1790 
1791  indexInfo->ii_ExclusionOps[attn] = opid;
1792  indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
1793  indexInfo->ii_ExclusionStrats[attn] = strat;
1794  nextExclOp = lnext(exclusionOpNames, nextExclOp);
1795  }
1796 
1797  /*
1798  * Set up the per-column options (indoption field). For now, this is
1799  * zero for any un-ordered index, while ordered indexes have DESC and
1800  * NULLS FIRST/LAST options.
1801  */
1802  colOptionP[attn] = 0;
1803  if (amcanorder)
1804  {
1805  /* default ordering is ASC */
1806  if (attribute->ordering == SORTBY_DESC)
1807  colOptionP[attn] |= INDOPTION_DESC;
1808  /* default null ordering is LAST for ASC, FIRST for DESC */
1809  if (attribute->nulls_ordering == SORTBY_NULLS_DEFAULT)
1810  {
1811  if (attribute->ordering == SORTBY_DESC)
1812  colOptionP[attn] |= INDOPTION_NULLS_FIRST;
1813  }
1814  else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
1815  colOptionP[attn] |= INDOPTION_NULLS_FIRST;
1816  }
1817  else
1818  {
1819  /* index AM does not support ordering */
1820  if (attribute->ordering != SORTBY_DEFAULT)
1821  ereport(ERROR,
1822  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1823  errmsg("access method \"%s\" does not support ASC/DESC options",
1824  accessMethodName)));
1825  if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
1826  ereport(ERROR,
1827  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1828  errmsg("access method \"%s\" does not support NULLS FIRST/LAST options",
1829  accessMethodName)));
1830  }
1831 
1832  attn++;
1833  }
1834 }
1835 
1836 /*
1837  * Resolve possibly-defaulted operator class specification
1838  *
1839  * Note: This is used to resolve operator class specifications in index and
1840  * partition key definitions.
1841  */
1842 Oid
1843 ResolveOpClass(List *opclass, Oid attrType,
1844  const char *accessMethodName, Oid accessMethodId)
1845 {
1846  char *schemaname;
1847  char *opcname;
1848  HeapTuple tuple;
1849  Form_pg_opclass opform;
1850  Oid opClassId,
1851  opInputType;
1852 
1853  if (opclass == NIL)
1854  {
1855  /* no operator class specified, so find the default */
1856  opClassId = GetDefaultOpClass(attrType, accessMethodId);
1857  if (!OidIsValid(opClassId))
1858  ereport(ERROR,
1859  (errcode(ERRCODE_UNDEFINED_OBJECT),
1860  errmsg("data type %s has no default operator class for access method \"%s\"",
1861  format_type_be(attrType), accessMethodName),
1862  errhint("You must specify an operator class for the index or define a default operator class for the data type.")));
1863  return opClassId;
1864  }
1865 
1866  /*
1867  * Specific opclass name given, so look up the opclass.
1868  */
1869 
1870  /* deconstruct the name list */
1871  DeconstructQualifiedName(opclass, &schemaname, &opcname);
1872 
1873  if (schemaname)
1874  {
1875  /* Look in specific schema only */
1876  Oid namespaceId;
1877 
1878  namespaceId = LookupExplicitNamespace(schemaname, false);
1879  tuple = SearchSysCache3(CLAAMNAMENSP,
1880  ObjectIdGetDatum(accessMethodId),
1881  PointerGetDatum(opcname),
1882  ObjectIdGetDatum(namespaceId));
1883  }
1884  else
1885  {
1886  /* Unqualified opclass name, so search the search path */
1887  opClassId = OpclassnameGetOpcid(accessMethodId, opcname);
1888  if (!OidIsValid(opClassId))
1889  ereport(ERROR,
1890  (errcode(ERRCODE_UNDEFINED_OBJECT),
1891  errmsg("operator class \"%s\" does not exist for access method \"%s\"",
1892  opcname, accessMethodName)));
1893  tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opClassId));
1894  }
1895 
1896  if (!HeapTupleIsValid(tuple))
1897  ereport(ERROR,
1898  (errcode(ERRCODE_UNDEFINED_OBJECT),
1899  errmsg("operator class \"%s\" does not exist for access method \"%s\"",
1900  NameListToString(opclass), accessMethodName)));
1901 
1902  /*
1903  * Verify that the index operator class accepts this datatype. Note we
1904  * will accept binary compatibility.
1905  */
1906  opform = (Form_pg_opclass) GETSTRUCT(tuple);
1907  opClassId = opform->oid;
1908  opInputType = opform->opcintype;
1909 
1910  if (!IsBinaryCoercible(attrType, opInputType))
1911  ereport(ERROR,
1912  (errcode(ERRCODE_DATATYPE_MISMATCH),
1913  errmsg("operator class \"%s\" does not accept data type %s",
1914  NameListToString(opclass), format_type_be(attrType))));
1915 
1916  ReleaseSysCache(tuple);
1917 
1918  return opClassId;
1919 }
1920 
1921 /*
1922  * GetDefaultOpClass
1923  *
1924  * Given the OIDs of a datatype and an access method, find the default
1925  * operator class, if any. Returns InvalidOid if there is none.
1926  */
1927 Oid
1928 GetDefaultOpClass(Oid type_id, Oid am_id)
1929 {
1930  Oid result = InvalidOid;
1931  int nexact = 0;
1932  int ncompatible = 0;
1933  int ncompatiblepreferred = 0;
1934  Relation rel;
1935  ScanKeyData skey[1];
1936  SysScanDesc scan;
1937  HeapTuple tup;
1938  TYPCATEGORY tcategory;
1939 
1940  /* If it's a domain, look at the base type instead */
1941  type_id = getBaseType(type_id);
1942 
1943  tcategory = TypeCategory(type_id);
1944 
1945  /*
1946  * We scan through all the opclasses available for the access method,
1947  * looking for one that is marked default and matches the target type
1948  * (either exactly or binary-compatibly, but prefer an exact match).
1949  *
1950  * We could find more than one binary-compatible match. If just one is
1951  * for a preferred type, use that one; otherwise we fail, forcing the user
1952  * to specify which one he wants. (The preferred-type special case is a
1953  * kluge for varchar: it's binary-compatible to both text and bpchar, so
1954  * we need a tiebreaker.) If we find more than one exact match, then
1955  * someone put bogus entries in pg_opclass.
1956  */
1957  rel = table_open(OperatorClassRelationId, AccessShareLock);
1958 
1959  ScanKeyInit(&skey[0],
1960  Anum_pg_opclass_opcmethod,
1961  BTEqualStrategyNumber, F_OIDEQ,
1962  ObjectIdGetDatum(am_id));
1963 
1964  scan = systable_beginscan(rel, OpclassAmNameNspIndexId, true,
1965  NULL, 1, skey);
1966 
1967  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1968  {
1969  Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
1970 
1971  /* ignore altogether if not a default opclass */
1972  if (!opclass->opcdefault)
1973  continue;
1974  if (opclass->opcintype == type_id)
1975  {
1976  nexact++;
1977  result = opclass->oid;
1978  }
1979  else if (nexact == 0 &&
1980  IsBinaryCoercible(type_id, opclass->opcintype))
1981  {
1982  if (IsPreferredType(tcategory, opclass->opcintype))
1983  {
1984  ncompatiblepreferred++;
1985  result = opclass->oid;
1986  }
1987  else if (ncompatiblepreferred == 0)
1988  {
1989  ncompatible++;
1990  result = opclass->oid;
1991  }
1992  }
1993  }
1994 
1995  systable_endscan(scan);
1996 
1998 
1999  /* raise error if pg_opclass contains inconsistent data */
2000  if (nexact > 1)
2001  ereport(ERROR,
2003  errmsg("there are multiple default operator classes for data type %s",
2004  format_type_be(type_id))));
2005 
2006  if (nexact == 1 ||
2007  ncompatiblepreferred == 1 ||
2008  (ncompatiblepreferred == 0 && ncompatible == 1))
2009  return result;
2010 
2011  return InvalidOid;
2012 }
2013 
2014 /*
2015  * makeObjectName()
2016  *
2017  * Create a name for an implicitly created index, sequence, constraint,
2018  * extended statistics, etc.
2019  *
2020  * The parameters are typically: the original table name, the original field
2021  * name, and a "type" string (such as "seq" or "pkey"). The field name
2022  * and/or type can be NULL if not relevant.
2023  *
2024  * The result is a palloc'd string.
2025  *
2026  * The basic result we want is "name1_name2_label", omitting "_name2" or
2027  * "_label" when those parameters are NULL. However, we must generate
2028  * a name with less than NAMEDATALEN characters! So, we truncate one or
2029  * both names if necessary to make a short-enough string. The label part
2030  * is never truncated (so it had better be reasonably short).
2031  *
2032  * The caller is responsible for checking uniqueness of the generated
2033  * name and retrying as needed; retrying will be done by altering the
2034  * "label" string (which is why we never truncate that part).
2035  */
2036 char *
2037 makeObjectName(const char *name1, const char *name2, const char *label)
2038 {
2039  char *name;
2040  int overhead = 0; /* chars needed for label and underscores */
2041  int availchars; /* chars available for name(s) */
2042  int name1chars; /* chars allocated to name1 */
2043  int name2chars; /* chars allocated to name2 */
2044  int ndx;
2045 
2046  name1chars = strlen(name1);
2047  if (name2)
2048  {
2049  name2chars = strlen(name2);
2050  overhead++; /* allow for separating underscore */
2051  }
2052  else
2053  name2chars = 0;
2054  if (label)
2055  overhead += strlen(label) + 1;
2056 
2057  availchars = NAMEDATALEN - 1 - overhead;
2058  Assert(availchars > 0); /* else caller chose a bad label */
2059 
2060  /*
2061  * If we must truncate, preferentially truncate the longer name. This
2062  * logic could be expressed without a loop, but it's simple and obvious as
2063  * a loop.
2064  */
2065  while (name1chars + name2chars > availchars)
2066  {
2067  if (name1chars > name2chars)
2068  name1chars--;
2069  else
2070  name2chars--;
2071  }
2072 
2073  name1chars = pg_mbcliplen(name1, name1chars, name1chars);
2074  if (name2)
2075  name2chars = pg_mbcliplen(name2, name2chars, name2chars);
2076 
2077  /* Now construct the string using the chosen lengths */
2078  name = palloc(name1chars + name2chars + overhead + 1);
2079  memcpy(name, name1, name1chars);
2080  ndx = name1chars;
2081  if (name2)
2082  {
2083  name[ndx++] = '_';
2084  memcpy(name + ndx, name2, name2chars);
2085  ndx += name2chars;
2086  }
2087  if (label)
2088  {
2089  name[ndx++] = '_';
2090  strcpy(name + ndx, label);
2091  }
2092  else
2093  name[ndx] = '\0';
2094 
2095  return name;
2096 }
2097 
2098 /*
2099  * Select a nonconflicting name for a new relation. This is ordinarily
2100  * used to choose index names (which is why it's here) but it can also
2101  * be used for sequences, or any autogenerated relation kind.
2102  *
2103  * name1, name2, and label are used the same way as for makeObjectName(),
2104  * except that the label can't be NULL; digits will be appended to the label
2105  * if needed to create a name that is unique within the specified namespace.
2106  *
2107  * If isconstraint is true, we also avoid choosing a name matching any
2108  * existing constraint in the same namespace. (This is stricter than what
2109  * Postgres itself requires, but the SQL standard says that constraint names
2110  * should be unique within schemas, so we follow that for autogenerated
2111  * constraint names.)
2112  *
2113  * Note: it is theoretically possible to get a collision anyway, if someone
2114  * else chooses the same name concurrently. This is fairly unlikely to be
2115  * a problem in practice, especially if one is holding an exclusive lock on
2116  * the relation identified by name1. However, if choosing multiple names
2117  * within a single command, you'd better create the new object and do
2118  * CommandCounterIncrement before choosing the next one!
2119  *
2120  * Returns a palloc'd string.
2121  */
2122 char *
2123 ChooseRelationName(const char *name1, const char *name2,
2124  const char *label, Oid namespaceid,
2125  bool isconstraint)
2126 {
2127  int pass = 0;
2128  char *relname = NULL;
2129  char modlabel[NAMEDATALEN];
2130 
2131  /* try the unmodified label first */
2132  StrNCpy(modlabel, label, sizeof(modlabel));
2133 
2134  for (;;)
2135  {
2136  relname = makeObjectName(name1, name2, modlabel);
2137 
2138  if (!OidIsValid(get_relname_relid(relname, namespaceid)))
2139  {
2140  if (!isconstraint ||
2141  !ConstraintNameExists(relname, namespaceid))
2142  break;
2143  }
2144 
2145  /* found a conflict, so try a new name component */
2146  pfree(relname);
2147  snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
2148  }
2149 
2150  return relname;
2151 }
2152 
2153 /*
2154  * Select the name to be used for an index.
2155  *
2156  * The argument list is pretty ad-hoc :-(
2157  */
2158 static char *
2159 ChooseIndexName(const char *tabname, Oid namespaceId,
2160  List *colnames, List *exclusionOpNames,
2161  bool primary, bool isconstraint)
2162 {
2163  char *indexname;
2164 
2165  if (primary)
2166  {
2167  /* the primary key's name does not depend on the specific column(s) */
2168  indexname = ChooseRelationName(tabname,
2169  NULL,
2170  "pkey",
2171  namespaceId,
2172  true);
2173  }
2174  else if (exclusionOpNames != NIL)
2175  {
2176  indexname = ChooseRelationName(tabname,
2177  ChooseIndexNameAddition(colnames),
2178  "excl",
2179  namespaceId,
2180  true);
2181  }
2182  else if (isconstraint)
2183  {
2184  indexname = ChooseRelationName(tabname,
2185  ChooseIndexNameAddition(colnames),
2186  "key",
2187  namespaceId,
2188  true);
2189  }
2190  else
2191  {
2192  indexname = ChooseRelationName(tabname,
2193  ChooseIndexNameAddition(colnames),
2194  "idx",
2195  namespaceId,
2196  false);
2197  }
2198 
2199  return indexname;
2200 }
2201 
2202 /*
2203  * Generate "name2" for a new index given the list of column names for it
2204  * (as produced by ChooseIndexColumnNames). This will be passed to
2205  * ChooseRelationName along with the parent table name and a suitable label.
2206  *
2207  * We know that less than NAMEDATALEN characters will actually be used,
2208  * so we can truncate the result once we've generated that many.
2209  *
2210  * XXX See also ChooseForeignKeyConstraintNameAddition and
2211  * ChooseExtendedStatisticNameAddition.
2212  */
2213 static char *
2215 {
2216  char buf[NAMEDATALEN * 2];
2217  int buflen = 0;
2218  ListCell *lc;
2219 
2220  buf[0] = '\0';
2221  foreach(lc, colnames)
2222  {
2223  const char *name = (const char *) lfirst(lc);
2224 
2225  if (buflen > 0)
2226  buf[buflen++] = '_'; /* insert _ between names */
2227 
2228  /*
2229  * At this point we have buflen <= NAMEDATALEN. name should be less
2230  * than NAMEDATALEN already, but use strlcpy for paranoia.
2231  */
2232  strlcpy(buf + buflen, name, NAMEDATALEN);
2233  buflen += strlen(buf + buflen);
2234  if (buflen >= NAMEDATALEN)
2235  break;
2236  }
2237  return pstrdup(buf);
2238 }
2239 
2240 /*
2241  * Select the actual names to be used for the columns of an index, given the
2242  * list of IndexElems for the columns. This is mostly about ensuring the
2243  * names are unique so we don't get a conflicting-attribute-names error.
2244  *
2245  * Returns a List of plain strings (char *, not String nodes).
2246  */
2247 static List *
2249 {
2250  List *result = NIL;
2251  ListCell *lc;
2252 
2253  foreach(lc, indexElems)
2254  {
2255  IndexElem *ielem = (IndexElem *) lfirst(lc);
2256  const char *origname;
2257  const char *curname;
2258  int i;
2259  char buf[NAMEDATALEN];
2260 
2261  /* Get the preliminary name from the IndexElem */
2262  if (ielem->indexcolname)
2263  origname = ielem->indexcolname; /* caller-specified name */
2264  else if (ielem->name)
2265  origname = ielem->name; /* simple column reference */
2266  else
2267  origname = "expr"; /* default name for expression */
2268 
2269  /* If it conflicts with any previous column, tweak it */
2270  curname = origname;
2271  for (i = 1;; i++)
2272  {
2273  ListCell *lc2;
2274  char nbuf[32];
2275  int nlen;
2276 
2277  foreach(lc2, result)
2278  {
2279  if (strcmp(curname, (char *) lfirst(lc2)) == 0)
2280  break;
2281  }
2282  if (lc2 == NULL)
2283  break; /* found nonconflicting name */
2284 
2285  sprintf(nbuf, "%d", i);
2286 
2287  /* Ensure generated names are shorter than NAMEDATALEN */
2288  nlen = pg_mbcliplen(origname, strlen(origname),
2289  NAMEDATALEN - 1 - strlen(nbuf));
2290  memcpy(buf, origname, nlen);
2291  strcpy(buf + nlen, nbuf);
2292  curname = buf;
2293  }
2294 
2295  /* And attach to the result list */
2296  result = lappend(result, pstrdup(curname));
2297  }
2298  return result;
2299 }
2300 
2301 /*
2302  * ReindexIndex
2303  * Recreate a specific index.
2304  */
2305 void
2306 ReindexIndex(RangeVar *indexRelation, int options, bool concurrent)
2307 {
2308  struct ReindexIndexCallbackState state;
2309  Oid indOid;
2310  Relation irel;
2311  char persistence;
2312 
2313  /*
2314  * Find and lock index, and check permissions on table; use callback to
2315  * obtain lock on table first, to avoid deadlock hazard. The lock level
2316  * used here must match the index lock obtained in reindex_index().
2317  *
2318  * If it's a temporary index, we will perform a non-concurrent reindex,
2319  * even if CONCURRENTLY was requested. In that case, reindex_index() will
2320  * upgrade the lock, but that's OK, because other sessions can't hold
2321  * locks on our temporary table.
2322  */
2323  state.concurrent = concurrent;
2324  state.locked_table_oid = InvalidOid;
2325  indOid = RangeVarGetRelidExtended(indexRelation,
2327  0,
2329  &state);
2330 
2331  /*
2332  * Obtain the current persistence of the existing index. We already hold
2333  * lock on the index.
2334  */
2335  irel = index_open(indOid, NoLock);
2336 
2337  if (irel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2338  {
2340  return;
2341  }
2342 
2343  persistence = irel->rd_rel->relpersistence;
2344  index_close(irel, NoLock);
2345 
2346  if (concurrent && persistence != RELPERSISTENCE_TEMP)
2347  ReindexRelationConcurrently(indOid, options);
2348  else
2349  reindex_index(indOid, false, persistence,
2350  options | REINDEXOPT_REPORT_PROGRESS);
2351 }
2352 
2353 /*
2354  * Check permissions on table before acquiring relation lock; also lock
2355  * the heap before the RangeVarGetRelidExtended takes the index lock, to avoid
2356  * deadlocks.
2357  */
2358 static void
2360  Oid relId, Oid oldRelId, void *arg)
2361 {
2362  char relkind;
2364  LOCKMODE table_lockmode;
2365 
2366  /*
2367  * Lock level here should match table lock in reindex_index() for
2368  * non-concurrent case and table locks used by index_concurrently_*() for
2369  * concurrent case.
2370  */
2371  table_lockmode = state->concurrent ? ShareUpdateExclusiveLock : ShareLock;
2372 
2373  /*
2374  * If we previously locked some other index's heap, and the name we're
2375  * looking up no longer refers to that relation, release the now-useless
2376  * lock.
2377  */
2378  if (relId != oldRelId && OidIsValid(oldRelId))
2379  {
2380  UnlockRelationOid(state->locked_table_oid, table_lockmode);
2381  state->locked_table_oid = InvalidOid;
2382  }
2383 
2384  /* If the relation does not exist, there's nothing more to do. */
2385  if (!OidIsValid(relId))
2386  return;
2387 
2388  /*
2389  * If the relation does exist, check whether it's an index. But note that
2390  * the relation might have been dropped between the time we did the name
2391  * lookup and now. In that case, there's nothing to do.
2392  */
2393  relkind = get_rel_relkind(relId);
2394  if (!relkind)
2395  return;
2396  if (relkind != RELKIND_INDEX &&
2397  relkind != RELKIND_PARTITIONED_INDEX)
2398  ereport(ERROR,
2399  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2400  errmsg("\"%s\" is not an index", relation->relname)));
2401 
2402  /* Check permissions */
2403  if (!pg_class_ownercheck(relId, GetUserId()))
2405 
2406  /* Lock heap before index to avoid deadlock. */
2407  if (relId != oldRelId)
2408  {
2409  Oid table_oid = IndexGetRelation(relId, true);
2410 
2411  /*
2412  * If the OID isn't valid, it means the index was concurrently
2413  * dropped, which is not a problem for us; just return normally.
2414  */
2415  if (OidIsValid(table_oid))
2416  {
2417  LockRelationOid(table_oid, table_lockmode);
2418  state->locked_table_oid = table_oid;
2419  }
2420  }
2421 }
2422 
2423 /*
2424  * ReindexTable
2425  * Recreate all indexes of a table (and of its toast table, if any)
2426  */
2427 Oid
2429 {
2430  Oid heapOid;
2431  bool result;
2432 
2433  /*
2434  * The lock level used here should match reindex_relation().
2435  *
2436  * If it's a temporary table, we will perform a non-concurrent reindex,
2437  * even if CONCURRENTLY was requested. In that case, reindex_relation()
2438  * will upgrade the lock, but that's OK, because other sessions can't hold
2439  * locks on our temporary table.
2440  */
2441  heapOid = RangeVarGetRelidExtended(relation,
2442  concurrent ? ShareUpdateExclusiveLock : ShareLock,
2443  0,
2445 
2446  if (concurrent && get_rel_persistence(heapOid) != RELPERSISTENCE_TEMP)
2447  {
2448  result = ReindexRelationConcurrently(heapOid, options);
2449 
2450  if (!result)
2451  ereport(NOTICE,
2452  (errmsg("table \"%s\" has no indexes that can be reindexed concurrently",
2453  relation->relname)));
2454  }
2455  else
2456  {
2457  result = reindex_relation(heapOid,
2460  options | REINDEXOPT_REPORT_PROGRESS);
2461  if (!result)
2462  ereport(NOTICE,
2463  (errmsg("table \"%s\" has no indexes to reindex",
2464  relation->relname)));
2465  }
2466 
2467  return heapOid;
2468 }
2469 
2470 /*
2471  * ReindexMultipleTables
2472  * Recreate indexes of tables selected by objectName/objectKind.
2473  *
2474  * To reduce the probability of deadlocks, each table is reindexed in a
2475  * separate transaction, so we can release the lock on it right away.
2476  * That means this must not be called within a user transaction block!
2477  */
2478 void
2479 ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
2480  int options, bool concurrent)
2481 {
2482  Oid objectOid;
2483  Relation relationRelation;
2484  TableScanDesc scan;
2485  ScanKeyData scan_keys[1];
2486  HeapTuple tuple;
2487  MemoryContext private_context;
2488  MemoryContext old;
2489  List *relids = NIL;
2490  ListCell *l;
2491  int num_keys;
2492  bool concurrent_warning = false;
2493 
2494  AssertArg(objectName);
2495  Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
2496  objectKind == REINDEX_OBJECT_SYSTEM ||
2497  objectKind == REINDEX_OBJECT_DATABASE);
2498 
2499  if (objectKind == REINDEX_OBJECT_SYSTEM && concurrent)
2500  ereport(ERROR,
2501  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2502  errmsg("cannot reindex system catalogs concurrently")));
2503 
2504  /*
2505  * Get OID of object to reindex, being the database currently being used
2506  * by session for a database or for system catalogs, or the schema defined
2507  * by caller. At the same time do permission checks that need different
2508  * processing depending on the object type.
2509  */
2510  if (objectKind == REINDEX_OBJECT_SCHEMA)
2511  {
2512  objectOid = get_namespace_oid(objectName, false);
2513 
2514  if (!pg_namespace_ownercheck(objectOid, GetUserId()))
2516  objectName);
2517  }
2518  else
2519  {
2520  objectOid = MyDatabaseId;
2521 
2522  if (strcmp(objectName, get_database_name(objectOid)) != 0)
2523  ereport(ERROR,
2524  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2525  errmsg("can only reindex the currently open database")));
2526  if (!pg_database_ownercheck(objectOid, GetUserId()))
2528  objectName);
2529  }
2530 
2531  /*
2532  * Create a memory context that will survive forced transaction commits we
2533  * do below. Since it is a child of PortalContext, it will go away
2534  * eventually even if we suffer an error; there's no need for special
2535  * abort cleanup logic.
2536  */
2537  private_context = AllocSetContextCreate(PortalContext,
2538  "ReindexMultipleTables",
2540 
2541  /*
2542  * Define the search keys to find the objects to reindex. For a schema, we
2543  * select target relations using relnamespace, something not necessary for
2544  * a database-wide operation.
2545  */
2546  if (objectKind == REINDEX_OBJECT_SCHEMA)
2547  {
2548  num_keys = 1;
2549  ScanKeyInit(&scan_keys[0],
2550  Anum_pg_class_relnamespace,
2551  BTEqualStrategyNumber, F_OIDEQ,
2552  ObjectIdGetDatum(objectOid));
2553  }
2554  else
2555  num_keys = 0;
2556 
2557  /*
2558  * Scan pg_class to build a list of the relations we need to reindex.
2559  *
2560  * We only consider plain relations and materialized views here (toast
2561  * rels will be processed indirectly by reindex_relation).
2562  */
2563  relationRelation = table_open(RelationRelationId, AccessShareLock);
2564  scan = table_beginscan_catalog(relationRelation, num_keys, scan_keys);
2565  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2566  {
2567  Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
2568  Oid relid = classtuple->oid;
2569 
2570  /*
2571  * Only regular tables and matviews can have indexes, so ignore any
2572  * other kind of relation.
2573  *
2574  * It is tempting to also consider partitioned tables here, but that
2575  * has the problem that if the children are in the same schema, they
2576  * would be processed twice. Maybe we could have a separate list of
2577  * partitioned tables, and expand that afterwards into relids,
2578  * ignoring any duplicates.
2579  */
2580  if (classtuple->relkind != RELKIND_RELATION &&
2581  classtuple->relkind != RELKIND_MATVIEW)
2582  continue;
2583 
2584  /* Skip temp tables of other backends; we can't reindex them at all */
2585  if (classtuple->relpersistence == RELPERSISTENCE_TEMP &&
2586  !isTempNamespace(classtuple->relnamespace))
2587  continue;
2588 
2589  /* Check user/system classification, and optionally skip */
2590  if (objectKind == REINDEX_OBJECT_SYSTEM &&
2591  !IsSystemClass(relid, classtuple))
2592  continue;
2593 
2594  /*
2595  * The table can be reindexed if the user is superuser, the table
2596  * owner, or the database/schema owner (but in the latter case, only
2597  * if it's not a shared relation). pg_class_ownercheck includes the
2598  * superuser case, and depending on objectKind we already know that
2599  * the user has permission to run REINDEX on this database or schema
2600  * per the permission checks at the beginning of this routine.
2601  */
2602  if (classtuple->relisshared &&
2603  !pg_class_ownercheck(relid, GetUserId()))
2604  continue;
2605 
2606  /*
2607  * Skip system tables, since index_create() would reject indexing them
2608  * concurrently (and it would likely fail if we tried).
2609  */
2610  if (concurrent &&
2611  IsCatalogRelationOid(relid))
2612  {
2613  if (!concurrent_warning)
2614  ereport(WARNING,
2615  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2616  errmsg("cannot reindex system catalogs concurrently, skipping all")));
2617  concurrent_warning = true;
2618  continue;
2619  }
2620 
2621  /* Save the list of relation OIDs in private context */
2622  old = MemoryContextSwitchTo(private_context);
2623 
2624  /*
2625  * We always want to reindex pg_class first if it's selected to be
2626  * reindexed. This ensures that if there is any corruption in
2627  * pg_class' indexes, they will be fixed before we process any other
2628  * tables. This is critical because reindexing itself will try to
2629  * update pg_class.
2630  */
2631  if (relid == RelationRelationId)
2632  relids = lcons_oid(relid, relids);
2633  else
2634  relids = lappend_oid(relids, relid);
2635 
2636  MemoryContextSwitchTo(old);
2637  }
2638  table_endscan(scan);
2639  table_close(relationRelation, AccessShareLock);
2640 
2641  /* Now reindex each rel in a separate transaction */
2644  foreach(l, relids)
2645  {
2646  Oid relid = lfirst_oid(l);
2647 
2649  /* functions in indexes may want a snapshot set */
2651 
2652  if (concurrent && get_rel_persistence(relid) != RELPERSISTENCE_TEMP)
2653  {
2654  (void) ReindexRelationConcurrently(relid, options);
2655  /* ReindexRelationConcurrently() does the verbose output */
2656  }
2657  else
2658  {
2659  bool result;
2660 
2661  result = reindex_relation(relid,
2664  options | REINDEXOPT_REPORT_PROGRESS);
2665 
2666  if (result && (options & REINDEXOPT_VERBOSE))
2667  ereport(INFO,
2668  (errmsg("table \"%s.%s\" was reindexed",
2670  get_rel_name(relid))));
2671 
2673  }
2674 
2676  }
2678 
2679  MemoryContextDelete(private_context);
2680 }
2681 
2682 
2683 /*
2684  * ReindexRelationConcurrently - process REINDEX CONCURRENTLY for given
2685  * relation OID
2686  *
2687  * 'relationOid' can either belong to an index, a table or a materialized
2688  * view. For tables and materialized views, all its indexes will be rebuilt,
2689  * excluding invalid indexes and any indexes used in exclusion constraints,
2690  * but including its associated toast table indexes. For indexes, the index
2691  * itself will be rebuilt. If 'relationOid' belongs to a partitioned table
2692  * then we issue a warning to mention these are not yet supported.
2693  *
2694  * The locks taken on parent tables and involved indexes are kept until the
2695  * transaction is committed, at which point a session lock is taken on each
2696  * relation. Both of these protect against concurrent schema changes.
2697  *
2698  * Returns true if any indexes have been rebuilt (including toast table's
2699  * indexes, when relevant), otherwise returns false.
2700  *
2701  * NOTE: This cannot be used on temporary relations. A concurrent build would
2702  * cause issues with ON COMMIT actions triggered by the transactions of the
2703  * concurrent build. Temporary relations are not subject to concurrent
2704  * concerns, so there's no need for the more complicated concurrent build,
2705  * anyway, and a non-concurrent reindex is more efficient.
2706  */
2707 static bool
2709 {
2710  List *heapRelationIds = NIL;
2711  List *indexIds = NIL;
2712  List *newIndexIds = NIL;
2713  List *relationLocks = NIL;
2714  List *lockTags = NIL;
2715  ListCell *lc,
2716  *lc2;
2717  MemoryContext private_context;
2718  MemoryContext oldcontext;
2719  char relkind;
2720  char *relationName = NULL;
2721  char *relationNamespace = NULL;
2722  PGRUsage ru0;
2723 
2724  /*
2725  * Create a memory context that will survive forced transaction commits we
2726  * do below. Since it is a child of PortalContext, it will go away
2727  * eventually even if we suffer an error; there's no need for special
2728  * abort cleanup logic.
2729  */
2730  private_context = AllocSetContextCreate(PortalContext,
2731  "ReindexConcurrent",
2733 
2734  if (options & REINDEXOPT_VERBOSE)
2735  {
2736  /* Save data needed by REINDEX VERBOSE in private context */
2737  oldcontext = MemoryContextSwitchTo(private_context);
2738 
2739  relationName = get_rel_name(relationOid);
2740  relationNamespace = get_namespace_name(get_rel_namespace(relationOid));
2741 
2742  pg_rusage_init(&ru0);
2743 
2744  MemoryContextSwitchTo(oldcontext);
2745  }
2746 
2747  relkind = get_rel_relkind(relationOid);
2748 
2749  /*
2750  * Extract the list of indexes that are going to be rebuilt based on the
2751  * relation Oid given by caller.
2752  */
2753  switch (relkind)
2754  {
2755  case RELKIND_RELATION:
2756  case RELKIND_MATVIEW:
2757  case RELKIND_TOASTVALUE:
2758  {
2759  /*
2760  * In the case of a relation, find all its indexes including
2761  * toast indexes.
2762  */
2763  Relation heapRelation;
2764 
2765  /* Save the list of relation OIDs in private context */
2766  oldcontext = MemoryContextSwitchTo(private_context);
2767 
2768  /* Track this relation for session locks */
2769  heapRelationIds = lappend_oid(heapRelationIds, relationOid);
2770 
2771  MemoryContextSwitchTo(oldcontext);
2772 
2773  if (IsCatalogRelationOid(relationOid))
2774  ereport(ERROR,
2775  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2776  errmsg("cannot reindex system catalogs concurrently")));
2777 
2778  /* Open relation to get its indexes */
2779  heapRelation = table_open(relationOid, ShareUpdateExclusiveLock);
2780 
2781  /* Add all the valid indexes of relation to list */
2782  foreach(lc, RelationGetIndexList(heapRelation))
2783  {
2784  Oid cellOid = lfirst_oid(lc);
2785  Relation indexRelation = index_open(cellOid,
2787 
2788  if (!indexRelation->rd_index->indisvalid)
2789  ereport(WARNING,
2790  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2791  errmsg("cannot reindex invalid index \"%s.%s\" concurrently, skipping",
2793  get_rel_name(cellOid))));
2794  else if (indexRelation->rd_index->indisexclusion)
2795  ereport(WARNING,
2796  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2797  errmsg("cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping",
2799  get_rel_name(cellOid))));
2800  else
2801  {
2802  /* Save the list of relation OIDs in private context */
2803  oldcontext = MemoryContextSwitchTo(private_context);
2804 
2805  indexIds = lappend_oid(indexIds, cellOid);
2806 
2807  MemoryContextSwitchTo(oldcontext);
2808  }
2809 
2810  index_close(indexRelation, NoLock);
2811  }
2812 
2813  /* Also add the toast indexes */
2814  if (OidIsValid(heapRelation->rd_rel->reltoastrelid))
2815  {
2816  Oid toastOid = heapRelation->rd_rel->reltoastrelid;
2817  Relation toastRelation = table_open(toastOid,
2819 
2820  /* Save the list of relation OIDs in private context */
2821  oldcontext = MemoryContextSwitchTo(private_context);
2822 
2823  /* Track this relation for session locks */
2824  heapRelationIds = lappend_oid(heapRelationIds, toastOid);
2825 
2826  MemoryContextSwitchTo(oldcontext);
2827 
2828  foreach(lc2, RelationGetIndexList(toastRelation))
2829  {
2830  Oid cellOid = lfirst_oid(lc2);
2831  Relation indexRelation = index_open(cellOid,
2833 
2834  if (!indexRelation->rd_index->indisvalid)
2835  ereport(WARNING,
2836  (errcode(ERRCODE_INDEX_CORRUPTED),
2837  errmsg("cannot reindex invalid index \"%s.%s\" concurrently, skipping",
2839  get_rel_name(cellOid))));
2840  else
2841  {
2842  /*
2843  * Save the list of relation OIDs in private
2844  * context
2845  */
2846  oldcontext = MemoryContextSwitchTo(private_context);
2847 
2848  indexIds = lappend_oid(indexIds, cellOid);
2849 
2850  MemoryContextSwitchTo(oldcontext);
2851  }
2852 
2853  index_close(indexRelation, NoLock);
2854  }
2855 
2856  table_close(toastRelation, NoLock);
2857  }
2858 
2859  table_close(heapRelation, NoLock);
2860  break;
2861  }
2862  case RELKIND_INDEX:
2863  {
2864  Oid heapId = IndexGetRelation(relationOid, false);
2865 
2866  if (IsCatalogRelationOid(heapId))
2867  ereport(ERROR,
2868  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2869  errmsg("cannot reindex system catalogs concurrently")));
2870 
2871  /*
2872  * Don't allow reindex for an invalid index on TOAST table, as
2873  * if rebuilt it would not be possible to drop it.
2874  */
2875  if (IsToastNamespace(get_rel_namespace(relationOid)) &&
2876  !get_index_isvalid(relationOid))
2877  ereport(ERROR,
2878  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2879  errmsg("cannot reindex invalid index on TOAST table concurrently")));
2880 
2881  /* Save the list of relation OIDs in private context */
2882  oldcontext = MemoryContextSwitchTo(private_context);
2883 
2884  /* Track the heap relation of this index for session locks */
2885  heapRelationIds = list_make1_oid(heapId);
2886 
2887  /*
2888  * Save the list of relation OIDs in private context. Note
2889  * that invalid indexes are allowed here.
2890  */
2891  indexIds = lappend_oid(indexIds, relationOid);
2892 
2893  MemoryContextSwitchTo(oldcontext);
2894  break;
2895  }
2896  case RELKIND_PARTITIONED_TABLE:
2897  /* see reindex_relation() */
2898  ereport(WARNING,
2899  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2900  errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
2901  get_rel_name(relationOid))));
2902  return false;
2903  default:
2904  /* Return error if type of relation is not supported */
2905  ereport(ERROR,
2906  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2907  errmsg("cannot reindex this type of relation concurrently")));
2908  break;
2909  }
2910 
2911  /* Definitely no indexes, so leave */
2912  if (indexIds == NIL)
2913  {
2915  return false;
2916  }
2917 
2918  Assert(heapRelationIds != NIL);
2919 
2920  /*-----
2921  * Now we have all the indexes we want to process in indexIds.
2922  *
2923  * The phases now are:
2924  *
2925  * 1. create new indexes in the catalog
2926  * 2. build new indexes
2927  * 3. let new indexes catch up with tuples inserted in the meantime
2928  * 4. swap index names
2929  * 5. mark old indexes as dead
2930  * 6. drop old indexes
2931  *
2932  * We process each phase for all indexes before moving to the next phase,
2933  * for efficiency.
2934  */
2935 
2936  /*
2937  * Phase 1 of REINDEX CONCURRENTLY
2938  *
2939  * Create a new index with the same properties as the old one, but it is
2940  * only registered in catalogs and will be built later. Then get session
2941  * locks on all involved tables. See analogous code in DefineIndex() for
2942  * more detailed comments.
2943  */
2944 
2945  foreach(lc, indexIds)
2946  {
2947  char *concurrentName;
2948  Oid indexId = lfirst_oid(lc);
2949  Oid newIndexId;
2950  Relation indexRel;
2951  Relation heapRel;
2952  Relation newIndexRel;
2953  LockRelId *lockrelid;
2954 
2955  indexRel = index_open(indexId, ShareUpdateExclusiveLock);
2956  heapRel = table_open(indexRel->rd_index->indrelid,
2958 
2959  /* This function shouldn't be called for temporary relations. */
2960  if (indexRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
2961  elog(ERROR, "cannot reindex a temporary table concurrently");
2962 
2964  RelationGetRelid(heapRel));
2968  indexId);
2970  indexRel->rd_rel->relam);
2971 
2972  /* Choose a temporary relation name for the new index */
2973  concurrentName = ChooseRelationName(get_rel_name(indexId),
2974  NULL,
2975  "ccnew",
2976  get_rel_namespace(indexRel->rd_index->indrelid),
2977  false);
2978 
2979  /* Create new index definition based on given index */
2980  newIndexId = index_concurrently_create_copy(heapRel,
2981  indexId,
2982  concurrentName);
2983 
2984  /*
2985  * Now open the relation of the new index, a session-level lock is
2986  * also needed on it.
2987  */
2988  newIndexRel = index_open(newIndexId, ShareUpdateExclusiveLock);
2989 
2990  /*
2991  * Save the list of OIDs and locks in private context
2992  */
2993  oldcontext = MemoryContextSwitchTo(private_context);
2994 
2995  newIndexIds = lappend_oid(newIndexIds, newIndexId);
2996 
2997  /*
2998  * Save lockrelid to protect each relation from drop then close
2999  * relations. The lockrelid on parent relation is not taken here to
3000  * avoid multiple locks taken on the same relation, instead we rely on
3001  * parentRelationIds built earlier.
3002  */
3003  lockrelid = palloc(sizeof(*lockrelid));
3004  *lockrelid = indexRel->rd_lockInfo.lockRelId;
3005  relationLocks = lappend(relationLocks, lockrelid);
3006  lockrelid = palloc(sizeof(*lockrelid));
3007  *lockrelid = newIndexRel->rd_lockInfo.lockRelId;
3008  relationLocks = lappend(relationLocks, lockrelid);
3009 
3010  MemoryContextSwitchTo(oldcontext);
3011 
3012  index_close(indexRel, NoLock);
3013  index_close(newIndexRel, NoLock);
3014  table_close(heapRel, NoLock);
3015  }
3016 
3017  /*
3018  * Save the heap lock for following visibility checks with other backends
3019  * might conflict with this session.
3020  */
3021  foreach(lc, heapRelationIds)
3022  {
3024  LockRelId *lockrelid;
3025  LOCKTAG *heaplocktag;
3026 
3027  /* Save the list of locks in private context */
3028  oldcontext = MemoryContextSwitchTo(private_context);
3029 
3030  /* Add lockrelid of heap relation to the list of locked relations */
3031  lockrelid = palloc(sizeof(*lockrelid));
3032  *lockrelid = heapRelation->rd_lockInfo.lockRelId;
3033  relationLocks = lappend(relationLocks, lockrelid);
3034 
3035  heaplocktag = (LOCKTAG *) palloc(sizeof(LOCKTAG));
3036 
3037  /* Save the LOCKTAG for this parent relation for the wait phase */
3038  SET_LOCKTAG_RELATION(*heaplocktag, lockrelid->dbId, lockrelid->relId);
3039  lockTags = lappend(lockTags, heaplocktag);
3040 
3041  MemoryContextSwitchTo(oldcontext);
3042 
3043  /* Close heap relation */
3044  table_close(heapRelation, NoLock);
3045  }
3046 
3047  /* Get a session-level lock on each table. */
3048  foreach(lc, relationLocks)
3049  {
3050  LockRelId *lockrelid = (LockRelId *) lfirst(lc);
3051 
3053  }
3054 
3058 
3059  /*
3060  * Phase 2 of REINDEX CONCURRENTLY
3061  *
3062  * Build the new indexes in a separate transaction for each index to avoid
3063  * having open transactions for an unnecessary long time. But before
3064  * doing that, wait until no running transactions could have the table of
3065  * the index open with the old list of indexes. See "phase 2" in
3066  * DefineIndex() for more details.
3067  */
3068 
3071  WaitForLockersMultiple(lockTags, ShareLock, true);
3073 
3074  forboth(lc, indexIds, lc2, newIndexIds)
3075  {
3076  Relation indexRel;
3077  Oid oldIndexId = lfirst_oid(lc);
3078  Oid newIndexId = lfirst_oid(lc2);
3079  Oid heapId;
3080 
3081  /* Start new transaction for this index's concurrent build */
3083 
3084  /*
3085  * Check for user-requested abort. This is inside a transaction so as
3086  * xact.c does not issue a useless WARNING, and ensures that
3087  * session-level locks are cleaned up on abort.
3088  */
3090 
3091  /* Set ActiveSnapshot since functions in the indexes may need it */
3093 
3094  /*
3095  * Index relation has been closed by previous commit, so reopen it to
3096  * get its information.
3097  */
3098  indexRel = index_open(oldIndexId, ShareUpdateExclusiveLock);
3099  heapId = indexRel->rd_index->indrelid;
3100  index_close(indexRel, NoLock);
3101 
3102  /* Perform concurrent build of new index */
3103  index_concurrently_build(heapId, newIndexId);
3104 
3107  }
3109 
3110  /*
3111  * Phase 3 of REINDEX CONCURRENTLY
3112  *
3113  * During this phase the old indexes catch up with any new tuples that
3114  * were created during the previous phase. See "phase 3" in DefineIndex()
3115  * for more details.
3116  */
3117 
3120  WaitForLockersMultiple(lockTags, ShareLock, true);
3122 
3123  foreach(lc, newIndexIds)
3124  {
3125  Oid newIndexId = lfirst_oid(lc);
3126  Oid heapId;
3127  TransactionId limitXmin;
3128  Snapshot snapshot;
3129 
3131 
3132  /*
3133  * Check for user-requested abort. This is inside a transaction so as
3134  * xact.c does not issue a useless WARNING, and ensures that
3135  * session-level locks are cleaned up on abort.
3136  */
3138 
3139  heapId = IndexGetRelation(newIndexId, false);
3140 
3141  /*
3142  * Take the "reference snapshot" that will be used by validate_index()
3143  * to filter candidate tuples.
3144  */
3146  PushActiveSnapshot(snapshot);
3147 
3148  validate_index(heapId, newIndexId, snapshot);
3149 
3150  /*
3151  * We can now do away with our active snapshot, we still need to save
3152  * the xmin limit to wait for older snapshots.
3153  */
3154  limitXmin = snapshot->xmin;
3155 
3157  UnregisterSnapshot(snapshot);
3158 
3159  /*
3160  * To ensure no deadlocks, we must commit and start yet another
3161  * transaction, and do our wait before any snapshot has been taken in
3162  * it.
3163  */
3166 
3167  /*
3168  * The index is now valid in the sense that it contains all currently
3169  * interesting tuples. But since it might not contain tuples deleted
3170  * just before the reference snap was taken, we have to wait out any
3171  * transactions that might have older snapshots.
3172  */
3175  WaitForOlderSnapshots(limitXmin, true);
3176 
3178  }
3179 
3180  /*
3181  * Phase 4 of REINDEX CONCURRENTLY
3182  *
3183  * Now that the new indexes have been validated, swap each new index with
3184  * its corresponding old index.
3185  *
3186  * We mark the new indexes as valid and the old indexes as not valid at
3187  * the same time to make sure we only get constraint violations from the
3188  * indexes with the correct names.
3189  */
3190 
3192 
3193  forboth(lc, indexIds, lc2, newIndexIds)
3194  {
3195  char *oldName;
3196  Oid oldIndexId = lfirst_oid(lc);
3197  Oid newIndexId = lfirst_oid(lc2);
3198  Oid heapId;
3199 
3200  /*
3201  * Check for user-requested abort. This is inside a transaction so as
3202  * xact.c does not issue a useless WARNING, and ensures that
3203  * session-level locks are cleaned up on abort.
3204  */
3206 
3207  heapId = IndexGetRelation(oldIndexId, false);
3208 
3209  /* Choose a relation name for old index */
3210  oldName = ChooseRelationName(get_rel_name(oldIndexId),
3211  NULL,
3212  "ccold",
3213  get_rel_namespace(heapId),
3214  false);
3215 
3216  /*
3217  * Swap old index with the new one. This also marks the new one as
3218  * valid and the old one as not valid.
3219  */
3220  index_concurrently_swap(newIndexId, oldIndexId, oldName);
3221 
3222  /*
3223  * Invalidate the relcache for the table, so that after this commit
3224  * all sessions will refresh any cached plans that might reference the
3225  * index.
3226  */
3228 
3229  /*
3230  * CCI here so that subsequent iterations see the oldName in the
3231  * catalog and can choose a nonconflicting name for their oldName.
3232  * Otherwise, this could lead to conflicts if a table has two indexes
3233  * whose names are equal for the first NAMEDATALEN-minus-a-few
3234  * characters.
3235  */
3237  }
3238 
3239  /* Commit this transaction and make index swaps visible */
3242 
3243  /*
3244  * Phase 5 of REINDEX CONCURRENTLY
3245  *
3246  * Mark the old indexes as dead. First we must wait until no running
3247  * transaction could be using the index for a query. See also
3248  * index_drop() for more details.
3249  */
3250 
3254 
3255  foreach(lc, indexIds)
3256  {
3257  Oid oldIndexId = lfirst_oid(lc);
3258  Oid heapId;
3259 
3260  /*
3261  * Check for user-requested abort. This is inside a transaction so as
3262  * xact.c does not issue a useless WARNING, and ensures that
3263  * session-level locks are cleaned up on abort.
3264  */
3266 
3267  heapId = IndexGetRelation(oldIndexId, false);
3268  index_concurrently_set_dead(heapId, oldIndexId);
3269  }
3270 
3271  /* Commit this transaction to make the updates visible. */
3274 
3275  /*
3276  * Phase 6 of REINDEX CONCURRENTLY
3277  *
3278  * Drop the old indexes.
3279  */
3280 
3284 
3286 
3287  {
3289 
3290  foreach(lc, indexIds)
3291  {
3292  Oid oldIndexId = lfirst_oid(lc);
3293  ObjectAddress object;
3294 
3295  object.classId = RelationRelationId;
3296  object.objectId = oldIndexId;
3297  object.objectSubId = 0;
3298 
3299  add_exact_object_address(&object, objects);
3300  }
3301 
3302  /*
3303  * Use PERFORM_DELETION_CONCURRENT_LOCK so that index_drop() uses the
3304  * right lock level.
3305  */
3308  }
3309 
3312 
3313  /*
3314  * Finally, release the session-level lock on the table.
3315  */
3316  foreach(lc, relationLocks)
3317  {
3318  LockRelId *lockrelid = (LockRelId *) lfirst(lc);
3319 
3321  }
3322 
3323  /* Start a new transaction to finish process properly */
3325 
3326  /* Log what we did */
3327  if (options & REINDEXOPT_VERBOSE)
3328  {
3329  if (relkind == RELKIND_INDEX)
3330  ereport(INFO,
3331  (errmsg("index \"%s.%s\" was reindexed",
3332  relationNamespace, relationName),
3333  errdetail("%s.",
3334  pg_rusage_show(&ru0))));
3335  else
3336  {
3337  foreach(lc, newIndexIds)
3338  {
3339  Oid indOid = lfirst_oid(lc);
3340 
3341  ereport(INFO,
3342  (errmsg("index \"%s.%s\" was reindexed",
3344  get_rel_name(indOid))));
3345  /* Don't show rusage here, since it's not per index. */
3346  }
3347 
3348  ereport(INFO,
3349  (errmsg("table \"%s.%s\" was reindexed",
3350  relationNamespace, relationName),
3351  errdetail("%s.",
3352  pg_rusage_show(&ru0))));
3353  }
3354  }
3355 
3356  MemoryContextDelete(private_context);
3357 
3359 
3360  return true;
3361 }
3362 
3363 /*
3364  * ReindexPartitionedIndex
3365  * Reindex each child of the given partitioned index.
3366  *
3367  * Not yet implemented.
3368  */
3369 static void
3371 {
3372  ereport(ERROR,
3373  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3374  errmsg("REINDEX is not yet implemented for partitioned indexes")));
3375 }
3376 
3377 /*
3378  * Insert or delete an appropriate pg_inherits tuple to make the given index
3379  * be a partition of the indicated parent index.
3380  *
3381  * This also corrects the pg_depend information for the affected index.
3382  */
3383 void
3384 IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
3385 {
3386  Relation pg_inherits;
3387  ScanKeyData key[2];
3388  SysScanDesc scan;
3389  Oid partRelid = RelationGetRelid(partitionIdx);
3390  HeapTuple tuple;
3391  bool fix_dependencies;
3392 
3393  /* Make sure this is an index */
3394  Assert(partitionIdx->rd_rel->relkind == RELKIND_INDEX ||
3395  partitionIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX);
3396 
3397  /*
3398  * Scan pg_inherits for rows linking our index to some parent.
3399  */
3400  pg_inherits = relation_open(InheritsRelationId, RowExclusiveLock);
3401  ScanKeyInit(&key[0],
3402  Anum_pg_inherits_inhrelid,
3403  BTEqualStrategyNumber, F_OIDEQ,
3404  ObjectIdGetDatum(partRelid));
3405  ScanKeyInit(&key[1],
3406  Anum_pg_inherits_inhseqno,
3407  BTEqualStrategyNumber, F_INT4EQ,
3408  Int32GetDatum(1));
3409  scan = systable_beginscan(pg_inherits, InheritsRelidSeqnoIndexId, true,
3410  NULL, 2, key);
3411  tuple = systable_getnext(scan);
3412 
3413  if (!HeapTupleIsValid(tuple))
3414  {
3415  if (parentOid == InvalidOid)
3416  {
3417  /*
3418  * No pg_inherits row, and no parent wanted: nothing to do in this
3419  * case.
3420  */
3421  fix_dependencies = false;
3422  }
3423  else
3424  {
3425  Datum values[Natts_pg_inherits];
3426  bool isnull[Natts_pg_inherits];
3427 
3428  /*
3429  * No pg_inherits row exists, and we want a parent for this index,
3430  * so insert it.
3431  */
3432  values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(partRelid);
3433  values[Anum_pg_inherits_inhparent - 1] =
3434  ObjectIdGetDatum(parentOid);
3435  values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(1);
3436  memset(isnull, false, sizeof(isnull));
3437 
3438  tuple = heap_form_tuple(RelationGetDescr(pg_inherits),
3439  values, isnull);
3440  CatalogTupleInsert(pg_inherits, tuple);
3441 
3442  fix_dependencies = true;
3443  }
3444  }
3445  else
3446  {
3447  Form_pg_inherits inhForm = (Form_pg_inherits) GETSTRUCT(tuple);
3448 
3449  if (parentOid == InvalidOid)
3450  {
3451  /*
3452  * There exists a pg_inherits row, which we want to clear; do so.
3453  */
3454  CatalogTupleDelete(pg_inherits, &tuple->t_self);
3455  fix_dependencies = true;
3456  }
3457  else
3458  {
3459  /*
3460  * A pg_inherits row exists. If it's the same we want, then we're
3461  * good; if it differs, that amounts to a corrupt catalog and
3462  * should not happen.
3463  */
3464  if (inhForm->inhparent != parentOid)
3465  {
3466  /* unexpected: we should not get called in this case */
3467  elog(ERROR, "bogus pg_inherit row: inhrelid %u inhparent %u",
3468  inhForm->inhrelid, inhForm->inhparent);
3469  }
3470 
3471  /* already in the right state */
3472  fix_dependencies = false;
3473  }
3474  }
3475 
3476  /* done with pg_inherits */
3477  systable_endscan(scan);
3478  relation_close(pg_inherits, RowExclusiveLock);
3479 
3480  /* set relhassubclass if an index partition has been added to the parent */
3481  if (OidIsValid(parentOid))
3482  SetRelationHasSubclass(parentOid, true);
3483 
3484  /* set relispartition correctly on the partition */
3485  update_relispartition(partRelid, OidIsValid(parentOid));
3486 
3487  if (fix_dependencies)
3488  {
3489  /*
3490  * Insert/delete pg_depend rows. If setting a parent, add PARTITION
3491  * dependencies on the parent index and the table; if removing a
3492  * parent, delete PARTITION dependencies.
3493  */
3494  if (OidIsValid(parentOid))
3495  {
3496  ObjectAddress partIdx;
3497  ObjectAddress parentIdx;
3498  ObjectAddress partitionTbl;
3499 
3500  ObjectAddressSet(partIdx, RelationRelationId, partRelid);
3501  ObjectAddressSet(parentIdx, RelationRelationId, parentOid);
3502  ObjectAddressSet(partitionTbl, RelationRelationId,
3503  partitionIdx->rd_index->indrelid);
3504  recordDependencyOn(&partIdx, &parentIdx,
3506  recordDependencyOn(&partIdx, &partitionTbl,
3508  }
3509  else
3510  {
3511  deleteDependencyRecordsForClass(RelationRelationId, partRelid,
3512  RelationRelationId,
3514  deleteDependencyRecordsForClass(RelationRelationId, partRelid,
3515  RelationRelationId,
3517  }
3518 
3519  /* make our updates visible */
3521  }
3522 }
3523 
3524 /*
3525  * Subroutine of IndexSetParentIndex to update the relispartition flag of the
3526  * given index to the given value.
3527  */
3528 static void
3530 {
3531  HeapTuple tup;
3532  Relation classRel;
3533 
3534  classRel = table_open(RelationRelationId, RowExclusiveLock);
3535  tup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
3536  if (!HeapTupleIsValid(tup))
3537  elog(ERROR, "cache lookup failed for relation %u", relationId);
3538  Assert(((Form_pg_class) GETSTRUCT(tup))->relispartition != newval);
3539  ((Form_pg_class) GETSTRUCT(tup))->relispartition = newval;
3540  CatalogTupleUpdate(classRel, &tup->t_self, tup);
3541  heap_freetuple(tup);
3542  table_close(classRel, RowExclusiveLock);
3543 }
bool deferrable
Definition: parsenodes.h:2788
#define PROGRESS_CREATEIDX_PHASE_WAIT_3
Definition: progress.h:97
signed short int16
Definition: c.h:354
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress)
Definition: lmgr.c:942
#define NIL
Definition: pg_list.h:65
Definition: c.h:594
bool primary
Definition: parsenodes.h:2786
VirtualTransactionId * GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
Definition: procarray.c:2494
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1416
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3395
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition: relcache.c:4998
void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment)
Definition: comment.c:142
bool CheckIndexCompatible(Oid oldId, const char *accessMethodName, List *attributeList, List *exclusionOpNames)
Definition: indexcmds.c:141
LockRelId lockRelId
Definition: rel.h:44
void RangeVarCallbackOwnsTable(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: tablecmds.c:15313
bool CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, Oid *collations1, Oid *collations2, Oid *opfamilies1, Oid *opfamilies2, AttrMap *attmap)
Definition: index.c:2403
bool amcanmulticol
Definition: amapi.h:183
#define IsA(nodeptr, _type_)
Definition: nodes.h:577
static bool CheckMutability(Expr *expr)
Definition: indexcmds.c:1478
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4703
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3043
static char * ChooseIndexNameAddition(List *colnames)
Definition: indexcmds.c:2214
ObjectAddress DefineIndex(Oid relationId, IndexStmt *stmt, Oid indexRelationId, Oid parentIndexId, Oid parentConstraintId, bool is_alter_table, bool check_rights, bool check_not_in_use, bool skip_build, bool quiet)
Definition: indexcmds.c:430
#define DEBUG1
Definition: elog.h:25
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1337
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2893
int errhint(const char *fmt,...)
Definition: elog.c:1071
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1928
#define PROGRESS_CREATEIDX_PARTITIONS_DONE
Definition: progress.h:87
Oid get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
SortByDir ordering
Definition: parsenodes.h:704
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
List * ii_Predicate
Definition: execnodes.h:162
Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, char *validnsps[], bool acceptOidsOff, bool isReset)
Definition: reloptions.c:904
List * options
Definition: parsenodes.h:2779
void free_attrmap(AttrMap *map)
Definition: attmap.c:57
Oid ReindexTable(RangeVar *relation, int options, bool concurrent)
Definition: indexcmds.c:2428
uint32 TransactionId
Definition: c.h:513
#define INDEX_CREATE_IF_NOT_EXISTS
Definition: index.h:51
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:865
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:98
amgettuple_function amgettuple
Definition: amapi.h:227
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
#define RelationGetDescr(relation)
Definition: rel.h:461
#define INDEX_CREATE_INVALID
Definition: index.h:53
int LOCKMODE
Definition: lockdefs.h:26
Oid GetUserId(void)
Definition: miscinit.c:439
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
Definition: pgstat.c:3140
void index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
Definition: index.c:3316
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:199
uint16 bits16
Definition: c.h:375
TransactionId xmin
Definition: proc.h:228
#define PointerGetDatum(X)
Definition: postgres.h:556
char * tableSpace
Definition: parsenodes.h:2775
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void pgstat_progress_update_param(int index, int64 val)
Definition: pgstat.c:3161
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1831
char * pstrdup(const char *in)
Definition: mcxt.c:1186
void CommitTransactionCommand(void)
Definition: xact.c:2898
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
Oid dbId
Definition: rel.h:39
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1780
Expr * expression_planner(Expr *expr)
Definition: planner.c:6044
#define REINDEXOPT_REPORT_PROGRESS
Definition: parsenodes.h:3346
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Node * whereClause
Definition: parsenodes.h:2780
Definition: lock.h:163
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:526
Oid * ii_ExclusionProcs
Definition: execnodes.h:165
void WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress)
Definition: lmgr.c:863
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PROGRESS_CREATEIDX_PHASE_WAIT_1
Definition: progress.h:91
#define INFO
Definition: elog.h:33
char * format_type_be(Oid type_oid)
Definition: format_type.c:327
static void WaitForOlderSnapshots(TransactionId limitXmin, bool progress)
Definition: indexcmds.c:340
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
char * format_operator(Oid operator_oid)
Definition: regproc.c:821
void PopActiveSnapshot(void)
Definition: snapmgr.c:814
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2809
bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
Definition: aclchk.c:4929
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2470
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
List * lcons_oid(Oid datum, List *list)
Definition: list.c:490
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:2300
bool ConstraintNameExists(const char *conname, Oid namespaceid)
void index_check_primary_key(Relation heapRel, IndexInfo *indexInfo, bool is_alter_table, IndexStmt *stmt)
Definition: index.c:200
char * ChooseRelationName(const char *name1, const char *name2, const char *label, Oid namespaceid, bool isconstraint)
Definition: indexcmds.c:2123
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2415
void index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
Definition: index.c:1447
Node * map_variable_attnos(Node *node, int target_varno, int sublevels_up, const AttrMap *attno_map, Oid to_rowtype, bool *found_whole_row)
static List * ChooseIndexColumnNames(List *indexElems)
Definition: indexcmds.c:2248
void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, int options, bool concurrent)
Definition: indexcmds.c:2479
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:195
PartitionKey RelationGetPartitionKey(Relation rel)
Definition: partcache.c:54
Form_pg_class rd_rel
Definition: rel.h:89
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
NameData relname
Definition: pg_class.h:38
void ReindexIndex(RangeVar *indexRelation, int options, bool concurrent)
Definition: indexcmds.c:2306
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
Definition: namespace.c:1800
Oid index_create(Relation heapRelation, const char *indexRelationName, Oid indexRelationId, Oid parentIndexRelid, Oid parentConstraintId, Oid relFileNode, 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:690
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:306
#define OidIsValid(objectId)
Definition: c.h:644
ReindexObjectType
Definition: parsenodes.h:3348
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4691
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
#define OpclassAmNameNspIndexId
Definition: indexing.h:195
bool IsPreferredType(TYPCATEGORY category, Oid type)
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
#define REINDEXOPT_VERBOSE
Definition: parsenodes.h:3345
Oid MyDatabaseTableSpace
Definition: globals.c:87
Definition: attmap.h:34
PGXACT * MyPgXact
Definition: proc.c:68
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:80
#define PROGRESS_CREATEIDX_COMMAND_REINDEX_CONCURRENTLY
Definition: progress.h:111
MemoryContext PortalContext
Definition: mcxt.c:53
bool IsCatalogRelationOid(Oid relid)
Definition: catalog.c:115
List * indexIncludingParams
Definition: parsenodes.h:2777
void pg_rusage_init(PGRUsage *ru0)
Definition: pg_rusage.c:27
#define INDEX_CONSTR_CREATE_INIT_DEFERRED
Definition: index.h:77
#define PROGRESS_CREATEIDX_PHASE_WAIT_4
Definition: progress.h:98
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4450
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:2037
#define NAMEDATALEN
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:73
void SetRelationHasSubclass(Oid relationId, bool relhassubclass)
Definition: tablecmds.c:2895
char * relname
Definition: primnodes.h:68
#define sprintf
Definition: port.h:194
Oid indexOid
Definition: parsenodes.h:2783
Node * expr
Definition: parsenodes.h:700
char TYPCATEGORY
Definition: parse_coerce.h:21
RangeVar * relation
Definition: parsenodes.h:2773
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
Form_pg_index rd_index
Definition: rel.h:154
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
unsigned short uint16
Definition: c.h:366
void pfree(void *pointer)
Definition: mcxt.c:1056
#define PROC_IN_VACUUM
Definition: proc.h:54
Oid * rd_indcollation
Definition: rel.h:179
SortByNulls nulls_ordering
Definition: parsenodes.h:705
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:382
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
int ii_NumIndexKeyAttrs
Definition: execnodes.h:158
#define PROGRESS_CREATEIDX_PHASE_WAIT_2
Definition: progress.h:93
Definition: rel.h:36
#define ACL_CREATE
Definition: parsenodes.h:84
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:369
amoptions_function amoptions
Definition: amapi.h:221
static bool ReindexRelationConcurrently(Oid relationOid, int options)
Definition: indexcmds.c:2708
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1138
ItemPointerData t_self
Definition: htup.h:65
bool has_superclass(Oid relationId)
Definition: pg_inherits.c:286
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:967
bool amcaninclude
Definition: amapi.h:199
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1713
Oid attcollation
Definition: pg_attribute.h:157
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
bool amcanunique
Definition: amapi.h:181
static void update_relispartition(Oid relationId, bool newval)
Definition: indexcmds.c:3529
Oid GetDefaultTablespace(char relpersistence, bool partitioned)
Definition: tablespace.c:1138
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:180
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3120
#define NoLock
Definition: lockdefs.h:34
LockInfoData rd_lockInfo
Definition: rel.h:92
static char * buf
Definition: pg_test_fsync.c:67
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1291
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:735
void IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
Definition: indexcmds.c:3384
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:553
#define PROGRESS_CREATEIDX_COMMAND_CREATE
Definition: progress.h:108
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:602
Oid ResolveOpClass(List *opclass, Oid attrType, const char *accessMethodName, Oid accessMethodId)
Definition: indexcmds.c:1843
#define RowExclusiveLock
Definition: lockdefs.h:38
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:5900
#define PROGRESS_CREATEIDX_INDEX_OID
Definition: progress.h:80
int errdetail(const char *fmt,...)
Definition: elog.c:957
char * indexcolname
Definition: parsenodes.h:701
PartitionDesc RelationGetPartitionDesc(Relation rel)
Definition: partdesc.c:65
const char * pg_rusage_show(const PGRUsage *ru0)
Definition: pg_rusage.c:40
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1329
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:469
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:236
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3157
Oid * rd_opfamily
Definition: rel.h:169
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:1191
TransactionId xmin
Definition: snapshot.h:157
Oid index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char *newName)
Definition: index.c:1240
void ConstraintSetParentConstraint(Oid childConstrId, Oid parentConstrId, Oid childTableId)
IndexInfo * makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, List *predicates, bool unique, bool isready, bool concurrent)
Definition: makefuncs.c:740
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3479
#define AssertArg(condition)
Definition: c.h:740
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5171
bool inh
Definition: primnodes.h:69
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:907
bool IsBinaryCoercible(Oid srctype, Oid targettype)
#define PROGRESS_WAITFOR_CURRENT_PID
Definition: progress.h:116
List * lappend(List *list, void *datum)
Definition: list.c:322
#define PROGRESS_CREATEIDX_PARTITIONS_TOTAL
Definition: progress.h:86
char * idxname
Definition: parsenodes.h:2772
#define WARNING
Definition: elog.h:40
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
void validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
Definition: index.c:3160
static void RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: indexcmds.c:2359
FormData_pg_index * Form_pg_index
Definition: pg_index.h:66
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3102
int progress
Definition: pgbench.c:234
#define PROGRESS_CREATEIDX_PHASE
Definition: progress.h:82
bool reset_default_tblspc
Definition: parsenodes.h:2793
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:51
bool if_not_exists
Definition: parsenodes.h:2792
AclResult
Definition: acl.h:177
AttrNumber * partattrs
Definition: partcache.h:28
void pgstat_progress_end_command(void)
Definition: pgstat.c:3212
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1005
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
static void fix_dependencies(ArchiveHandle *AH)
int ii_NumIndexAttrs
Definition: execnodes.h:157
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:716
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define list_make1_oid(x1)
Definition: pg_list.h:249
static char * label
Oid MyDatabaseId
Definition: globals.c:85
bool unique
Definition: parsenodes.h:2785
TupleDesc rd_att
Definition: rel.h:90
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:240
char * accessMethod
Definition: parsenodes.h:2774
#define INDEX_CREATE_IS_PRIMARY
Definition: index.h:47
bool allowSystemTableMods
Definition: globals.c:120
#define InvalidOid
Definition: postgres_ext.h:36
#define INDEX_CREATE_CONCURRENT
Definition: index.h:50
TYPCATEGORY TypeCategory(Oid type)
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1118
#define ereport(elevel,...)
Definition: elog.h:144
bytea * index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
Definition: reloptions.c:1701
List * opclass
Definition: parsenodes.h:703
AttrMap * build_attrmap_by_name(TupleDesc indesc, TupleDesc outdesc)
Definition: attmap.c:174
#define NOTICE
Definition: elog.h:37
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * ii_Expressions
Definition: execnodes.h:160
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
#define StrNCpy(dst, src, len)
Definition: c.h:944
Definition: regguts.h:298
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:565
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4753
void StartTransactionCommand(void)
Definition: xact.c:2797
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:76
List * indexParams
Definition: parsenodes.h:2776
static void CheckPredicate(Expr *predicate)
Definition: indexcmds.c:1512
#define INDEX_MAX_KEYS
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:171
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
bool get_index_isvalid(Oid index_oid)
Definition: lsyscache.c:3286
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:44
#define PROGRESS_WAITFOR_DONE
Definition: progress.h:115
List * excludeOpNames
Definition: parsenodes.h:2781
static int list_length(const List *l)
Definition: pg_list.h:169
#define newval
#define REINDEX_REL_CHECK_CONSTRAINTS
Definition: index.h:140
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:719
#define PROGRESS_CREATEIDX_COMMAND_CREATE_CONCURRENTLY
Definition: progress.h:109
bool initdeferred
Definition: parsenodes.h:2789
bool amcanorder
Definition: amapi.h:175
char * name
Definition: parsenodes.h:699
char * idxcomment
Definition: parsenodes.h:2782
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1045
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4330
void reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, int options)
Definition: index.c:3420
const char * name
Definition: encode.c:521
#define InvalidAttrNumber
Definition: attnum.h:23
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:152
#define DatumGetPointer(X)
Definition: postgres.h:549
char get_rel_persistence(Oid relid)
Definition: lsyscache.c:1906
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:863
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:81
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define INDEX_CREATE_SKIP_BUILD
Definition: index.h:49
bool concurrent
Definition: parsenodes.h:2791
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define INDEX_CREATE_PARTITIONED
Definition: index.h:52
#define Int32GetDatum(X)
Definition: postgres.h:479
int NewGUCNestLevel(void)
Definition: guc.c:5886
bool isconstraint
Definition: parsenodes.h:2787
Oid * ii_ExclusionOps
Definition: execnodes.h:164
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
Definition: parse_oper.c:494
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1462
void list_free(List *list)
Definition: list.c:1377
#define elog(elevel,...)
Definition: elog.h:214
#define ShareLock
Definition: lockdefs.h:41
int i
#define PERFORM_DELETION_CONCURRENT_LOCK
Definition: dependency.h:139
#define NameStr(name)
Definition: c.h:615
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
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)
Definition: indexcmds.c:1535
void * arg
List * collation
Definition: parsenodes.h:702
#define REINDEX_REL_PROCESS_TOAST
Definition: index.h:138
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:647
static char * ChooseIndexName(const char *tabname, Oid namespaceId, List *colnames, List *exclusionOpNames, bool primary, bool isconstraint)
Definition: indexcmds.c:2159
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
bytea *(* amoptions_function)(Datum reloptions, bool validate)
Definition: amapi.h:103
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:375
#define copyObject(obj)
Definition: nodes.h:642
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:159
uint16 * ii_ExclusionStrats
Definition: execnodes.h:166
static void ReindexPartitionedIndex(Relation parentIdx)
Definition: indexcmds.c:3370
#define PROGRESS_WAITFOR_TOTAL
Definition: progress.h:114
#define INDEX_CREATE_ADD_CONSTRAINT
Definition: index.h:48
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void index_concurrently_set_dead(Oid heapId, Oid indexId)
Definition: index.c:1733
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2325
void index_concurrently_build(Oid heapRelationId, Oid indexRelationId)
Definition: index.c:1399
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2874
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
Definition: proc.h:95
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:6893
bool reindex_relation(Oid relid, int flags, int options)
Definition: index.c:3664
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3601
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1756
#define snprintf
Definition: port.h:192
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
int pid
Definition: proc.h:109
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:435
#define INDEX_CONSTR_CREATE_DEFERRABLE
Definition: index.h:76
#define PROGRESS_CREATEIDX_COMMAND
Definition: progress.h:79
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:126
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PROC_IS_AUTOVACUUM
Definition: proc.h:53
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:134
Oid relId
Definition: rel.h:38
#define PROGRESS_CREATEIDX_ACCESS_METHOD_OID
Definition: progress.h:81
PGPROC * BackendIdGetProc(int backendID)
Definition: sinvaladt.c:376
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1067
#define RelationGetNamespace(relation)
Definition: rel.h:476