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-2018, 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/htup_details.h"
20 #include "access/reloptions.h"
21 #include "access/sysattr.h"
22 #include "access/xact.h"
23 #include "catalog/catalog.h"
24 #include "catalog/index.h"
25 #include "catalog/indexing.h"
26 #include "catalog/partition.h"
27 #include "catalog/pg_am.h"
28 #include "catalog/pg_constraint.h"
29 #include "catalog/pg_inherits.h"
30 #include "catalog/pg_opclass.h"
31 #include "catalog/pg_opfamily.h"
32 #include "catalog/pg_tablespace.h"
33 #include "catalog/pg_type.h"
34 #include "commands/comment.h"
35 #include "commands/dbcommands.h"
36 #include "commands/defrem.h"
37 #include "commands/tablecmds.h"
38 #include "commands/tablespace.h"
39 #include "mb/pg_wchar.h"
40 #include "miscadmin.h"
41 #include "nodes/makefuncs.h"
42 #include "nodes/nodeFuncs.h"
43 #include "optimizer/clauses.h"
44 #include "optimizer/planner.h"
45 #include "optimizer/var.h"
46 #include "parser/parse_coerce.h"
47 #include "parser/parse_func.h"
48 #include "parser/parse_oper.h"
49 #include "rewrite/rewriteManip.h"
50 #include "storage/lmgr.h"
51 #include "storage/proc.h"
52 #include "storage/procarray.h"
53 #include "utils/acl.h"
54 #include "utils/builtins.h"
55 #include "utils/fmgroids.h"
56 #include "utils/inval.h"
57 #include "utils/lsyscache.h"
58 #include "utils/memutils.h"
59 #include "utils/partcache.h"
60 #include "utils/regproc.h"
61 #include "utils/snapmgr.h"
62 #include "utils/syscache.h"
63 #include "utils/tqual.h"
64 
65 
66 /* non-export function prototypes */
67 static void CheckPredicate(Expr *predicate);
68 static void ComputeIndexAttrs(IndexInfo *indexInfo,
69  Oid *typeOidP,
70  Oid *collationOidP,
71  Oid *classOidP,
72  int16 *colOptionP,
73  List *attList,
74  List *exclusionOpNames,
75  Oid relId,
76  const char *accessMethodName, Oid accessMethodId,
77  bool amcanorder,
78  bool isconstraint);
79 static char *ChooseIndexName(const char *tabname, Oid namespaceId,
80  List *colnames, List *exclusionOpNames,
81  bool primary, bool isconstraint);
82 static char *ChooseIndexNameAddition(List *colnames);
83 static List *ChooseIndexColumnNames(List *indexElems);
84 static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
85  Oid relId, Oid oldRelId, void *arg);
86 static void ReindexPartitionedIndex(Relation parentIdx);
87 
88 /*
89  * CheckIndexCompatible
90  * Determine whether an existing index definition is compatible with a
91  * prospective index definition, such that the existing index storage
92  * could become the storage of the new index, avoiding a rebuild.
93  *
94  * 'heapRelation': the relation the index would apply to.
95  * 'accessMethodName': name of the AM to use.
96  * 'attributeList': a list of IndexElem specifying columns and expressions
97  * to index on.
98  * 'exclusionOpNames': list of names of exclusion-constraint operators,
99  * or NIL if not an exclusion constraint.
100  *
101  * This is tailored to the needs of ALTER TABLE ALTER TYPE, which recreates
102  * any indexes that depended on a changing column from their pg_get_indexdef
103  * or pg_get_constraintdef definitions. We omit some of the sanity checks of
104  * DefineIndex. We assume that the old and new indexes have the same number
105  * of columns and that if one has an expression column or predicate, both do.
106  * Errors arising from the attribute list still apply.
107  *
108  * Most column type changes that can skip a table rewrite do not invalidate
109  * indexes. We acknowledge this when all operator classes, collations and
110  * exclusion operators match. Though we could further permit intra-opfamily
111  * changes for btree and hash indexes, that adds subtle complexity with no
112  * concrete benefit for core types. Note, that INCLUDE columns aren't
113  * checked by this function, for them it's enough that table rewrite is
114  * skipped.
115  *
116  * When a comparison or exclusion operator has a polymorphic input type, the
117  * actual input types must also match. This defends against the possibility
118  * that operators could vary behavior in response to get_fn_expr_argtype().
119  * At present, this hazard is theoretical: check_exclusion_constraint() and
120  * all core index access methods decline to set fn_expr for such calls.
121  *
122  * We do not yet implement a test to verify compatibility of expression
123  * columns or predicates, so assume any such index is incompatible.
124  */
125 bool
127  const char *accessMethodName,
128  List *attributeList,
129  List *exclusionOpNames)
130 {
131  bool isconstraint;
132  Oid *typeObjectId;
133  Oid *collationObjectId;
134  Oid *classObjectId;
135  Oid accessMethodId;
136  Oid relationId;
137  HeapTuple tuple;
138  Form_pg_index indexForm;
139  Form_pg_am accessMethodForm;
140  IndexAmRoutine *amRoutine;
141  bool amcanorder;
142  int16 *coloptions;
143  IndexInfo *indexInfo;
144  int numberOfAttributes;
145  int old_natts;
146  bool isnull;
147  bool ret = true;
148  oidvector *old_indclass;
149  oidvector *old_indcollation;
150  Relation irel;
151  int i;
152  Datum d;
153 
154  /* Caller should already have the relation locked in some way. */
155  relationId = IndexGetRelation(oldId, false);
156 
157  /*
158  * We can pretend isconstraint = false unconditionally. It only serves to
159  * decide the text of an error message that should never happen for us.
160  */
161  isconstraint = false;
162 
163  numberOfAttributes = list_length(attributeList);
164  Assert(numberOfAttributes > 0);
165  Assert(numberOfAttributes <= INDEX_MAX_KEYS);
166 
167  /* look up the access method */
168  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
169  if (!HeapTupleIsValid(tuple))
170  ereport(ERROR,
171  (errcode(ERRCODE_UNDEFINED_OBJECT),
172  errmsg("access method \"%s\" does not exist",
173  accessMethodName)));
174  accessMethodId = HeapTupleGetOid(tuple);
175  accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
176  amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
177  ReleaseSysCache(tuple);
178 
179  amcanorder = amRoutine->amcanorder;
180 
181  /*
182  * Compute the operator classes, collations, and exclusion operators for
183  * the new index, so we can test whether it's compatible with the existing
184  * one. Note that ComputeIndexAttrs might fail here, but that's OK:
185  * DefineIndex would have called this function with the same arguments
186  * later on, and it would have failed then anyway. Our attributeList
187  * contains only key attributes, thus we're filling ii_NumIndexAttrs and
188  * ii_NumIndexKeyAttrs with same value.
189  */
190  indexInfo = makeNode(IndexInfo);
191  indexInfo->ii_NumIndexAttrs = numberOfAttributes;
192  indexInfo->ii_NumIndexKeyAttrs = numberOfAttributes;
193  indexInfo->ii_Expressions = NIL;
194  indexInfo->ii_ExpressionsState = NIL;
195  indexInfo->ii_PredicateState = NULL;
196  indexInfo->ii_ExclusionOps = NULL;
197  indexInfo->ii_ExclusionProcs = NULL;
198  indexInfo->ii_ExclusionStrats = NULL;
199  indexInfo->ii_Am = accessMethodId;
200  indexInfo->ii_AmCache = NULL;
201  indexInfo->ii_Context = CurrentMemoryContext;
202  typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
203  collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
204  classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
205  coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16));
206  ComputeIndexAttrs(indexInfo,
207  typeObjectId, collationObjectId, classObjectId,
208  coloptions, attributeList,
209  exclusionOpNames, relationId,
210  accessMethodName, accessMethodId,
211  amcanorder, isconstraint);
212 
213 
214  /* Get the soon-obsolete pg_index tuple. */
216  if (!HeapTupleIsValid(tuple))
217  elog(ERROR, "cache lookup failed for index %u", oldId);
218  indexForm = (Form_pg_index) GETSTRUCT(tuple);
219 
220  /*
221  * We don't assess expressions or predicates; assume incompatibility.
222  * Also, if the index is invalid for any reason, treat it as incompatible.
223  */
224  if (!(heap_attisnull(tuple, Anum_pg_index_indpred, NULL) &&
225  heap_attisnull(tuple, Anum_pg_index_indexprs, NULL) &&
226  IndexIsValid(indexForm)))
227  {
228  ReleaseSysCache(tuple);
229  return false;
230  }
231 
232  /* Any change in operator class or collation breaks compatibility. */
233  old_natts = indexForm->indnkeyatts;
234  Assert(old_natts == numberOfAttributes);
235 
236  d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indcollation, &isnull);
237  Assert(!isnull);
238  old_indcollation = (oidvector *) DatumGetPointer(d);
239 
240  d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indclass, &isnull);
241  Assert(!isnull);
242  old_indclass = (oidvector *) DatumGetPointer(d);
243 
244  ret = (memcmp(old_indclass->values, classObjectId,
245  old_natts * sizeof(Oid)) == 0 &&
246  memcmp(old_indcollation->values, collationObjectId,
247  old_natts * sizeof(Oid)) == 0);
248 
249  ReleaseSysCache(tuple);
250 
251  if (!ret)
252  return false;
253 
254  /* For polymorphic opcintype, column type changes break compatibility. */
255  irel = index_open(oldId, AccessShareLock); /* caller probably has a lock */
256  for (i = 0; i < old_natts; i++)
257  {
258  if (IsPolymorphicType(get_opclass_input_type(classObjectId[i])) &&
259  TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i])
260  {
261  ret = false;
262  break;
263  }
264  }
265 
266  /* Any change in exclusion operator selections breaks compatibility. */
267  if (ret && indexInfo->ii_ExclusionOps != NULL)
268  {
269  Oid *old_operators,
270  *old_procs;
271  uint16 *old_strats;
272 
273  RelationGetExclusionInfo(irel, &old_operators, &old_procs, &old_strats);
274  ret = memcmp(old_operators, indexInfo->ii_ExclusionOps,
275  old_natts * sizeof(Oid)) == 0;
276 
277  /* Require an exact input type match for polymorphic operators. */
278  if (ret)
279  {
280  for (i = 0; i < old_natts && ret; i++)
281  {
282  Oid left,
283  right;
284 
285  op_input_types(indexInfo->ii_ExclusionOps[i], &left, &right);
286  if ((IsPolymorphicType(left) || IsPolymorphicType(right)) &&
287  TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i])
288  {
289  ret = false;
290  break;
291  }
292  }
293  }
294  }
295 
296  index_close(irel, NoLock);
297  return ret;
298 }
299 
300 /*
301  * DefineIndex
302  * Creates a new index.
303  *
304  * 'relationId': the OID of the heap relation on which the index is to be
305  * created
306  * 'stmt': IndexStmt describing the properties of the new index.
307  * 'indexRelationId': normally InvalidOid, but during bootstrap can be
308  * nonzero to specify a preselected OID for the index.
309  * 'parentIndexId': the OID of the parent index; InvalidOid if not the child
310  * of a partitioned index.
311  * 'parentConstraintId': the OID of the parent constraint; InvalidOid if not
312  * the child of a constraint (only used when recursing)
313  * 'is_alter_table': this is due to an ALTER rather than a CREATE operation.
314  * 'check_rights': check for CREATE rights in namespace and tablespace. (This
315  * should be true except when ALTER is deleting/recreating an index.)
316  * 'check_not_in_use': check for table not already in use in current session.
317  * This should be true unless caller is holding the table open, in which
318  * case the caller had better have checked it earlier.
319  * 'skip_build': make the catalog entries but don't create the index files
320  * 'quiet': suppress the NOTICE chatter ordinarily provided for constraints.
321  *
322  * Returns the object address of the created index.
323  */
325 DefineIndex(Oid relationId,
326  IndexStmt *stmt,
327  Oid indexRelationId,
328  Oid parentIndexId,
329  Oid parentConstraintId,
330  bool is_alter_table,
331  bool check_rights,
332  bool check_not_in_use,
333  bool skip_build,
334  bool quiet)
335 {
336  char *indexRelationName;
337  char *accessMethodName;
338  Oid *typeObjectId;
339  Oid *collationObjectId;
340  Oid *classObjectId;
341  Oid accessMethodId;
342  Oid namespaceId;
343  Oid tablespaceId;
344  Oid createdConstraintId = InvalidOid;
345  List *indexColNames;
346  List *allIndexParams;
347  Relation rel;
348  Relation indexRelation;
349  HeapTuple tuple;
350  Form_pg_am accessMethodForm;
351  IndexAmRoutine *amRoutine;
352  bool amcanorder;
353  amoptions_function amoptions;
354  bool partitioned;
355  Datum reloptions;
356  int16 *coloptions;
357  IndexInfo *indexInfo;
358  bits16 flags;
359  bits16 constr_flags;
360  int numberOfAttributes;
361  int numberOfKeyAttributes;
362  TransactionId limitXmin;
363  VirtualTransactionId *old_snapshots;
364  ObjectAddress address;
365  int n_old_snapshots;
366  LockRelId heaprelid;
367  LOCKTAG heaplocktag;
368  LOCKMODE lockmode;
369  Snapshot snapshot;
370  int i;
371 
373  ereport(ERROR,
374  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
375  errmsg("included columns must not intersect with key columns")));
376 
377  /*
378  * count key attributes in index
379  */
380  numberOfKeyAttributes = list_length(stmt->indexParams);
381 
382  /*
383  * Calculate the new list of index columns including both key columns and
384  * INCLUDE columns. Later we can determine which of these are key
385  * columns, and which are just part of the INCLUDE list by checking the
386  * list position. A list item in a position less than ii_NumIndexKeyAttrs
387  * is part of the key columns, and anything equal to and over is part of
388  * the INCLUDE columns.
389  */
390  allIndexParams = list_concat(list_copy(stmt->indexParams),
392  numberOfAttributes = list_length(allIndexParams);
393 
394  if (numberOfAttributes <= 0)
395  ereport(ERROR,
396  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
397  errmsg("must specify at least one column")));
398  if (numberOfAttributes > INDEX_MAX_KEYS)
399  ereport(ERROR,
400  (errcode(ERRCODE_TOO_MANY_COLUMNS),
401  errmsg("cannot use more than %d columns in an index",
402  INDEX_MAX_KEYS)));
403 
404  /*
405  * Only SELECT ... FOR UPDATE/SHARE are allowed while doing a standard
406  * index build; but for concurrent builds we allow INSERT/UPDATE/DELETE
407  * (but not VACUUM).
408  *
409  * NB: Caller is responsible for making sure that relationId refers to the
410  * relation on which the index should be built; except in bootstrap mode,
411  * this will typically require the caller to have already locked the
412  * relation. To avoid lock upgrade hazards, that lock should be at least
413  * as strong as the one we take here.
414  *
415  * NB: If the lock strength here ever changes, code that is run by
416  * parallel workers under the control of certain particular ambuild
417  * functions will need to be updated, too.
418  */
419  lockmode = stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock;
420  rel = heap_open(relationId, lockmode);
421 
422  relationId = RelationGetRelid(rel);
423  namespaceId = RelationGetNamespace(rel);
424 
425  /* Ensure that it makes sense to index this kind of relation */
426  switch (rel->rd_rel->relkind)
427  {
428  case RELKIND_RELATION:
429  case RELKIND_MATVIEW:
430  case RELKIND_PARTITIONED_TABLE:
431  /* OK */
432  break;
433  case RELKIND_FOREIGN_TABLE:
434 
435  /*
436  * Custom error message for FOREIGN TABLE since the term is close
437  * to a regular table and can confuse the user.
438  */
439  ereport(ERROR,
440  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
441  errmsg("cannot create index on foreign table \"%s\"",
442  RelationGetRelationName(rel))));
443  break;
444  default:
445  ereport(ERROR,
446  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
447  errmsg("\"%s\" is not a table or materialized view",
448  RelationGetRelationName(rel))));
449  break;
450  }
451 
452  /*
453  * Establish behavior for partitioned tables, and verify sanity of
454  * parameters.
455  *
456  * We do not build an actual index in this case; we only create a few
457  * catalog entries. The actual indexes are built by recursing for each
458  * partition.
459  */
460  partitioned = rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
461  if (partitioned)
462  {
463  if (stmt->concurrent)
464  ereport(ERROR,
465  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
466  errmsg("cannot create index on partitioned table \"%s\" concurrently",
467  RelationGetRelationName(rel))));
468  if (stmt->excludeOpNames)
469  ereport(ERROR,
470  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
471  errmsg("cannot create exclusion constraints on partitioned table \"%s\"",
472  RelationGetRelationName(rel))));
473  }
474 
475  /*
476  * Don't try to CREATE INDEX on temp tables of other backends.
477  */
478  if (RELATION_IS_OTHER_TEMP(rel))
479  ereport(ERROR,
480  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
481  errmsg("cannot create indexes on temporary tables of other sessions")));
482 
483  /*
484  * Unless our caller vouches for having checked this already, insist that
485  * the table not be in use by our own session, either. Otherwise we might
486  * fail to make entries in the new index (for instance, if an INSERT or
487  * UPDATE is in progress and has already made its list of target indexes).
488  */
489  if (check_not_in_use)
490  CheckTableNotInUse(rel, "CREATE INDEX");
491 
492  /*
493  * Verify we (still) have CREATE rights in the rel's namespace.
494  * (Presumably we did when the rel was created, but maybe not anymore.)
495  * Skip check if caller doesn't want it. Also skip check if
496  * bootstrapping, since permissions machinery may not be working yet.
497  */
498  if (check_rights && !IsBootstrapProcessingMode())
499  {
500  AclResult aclresult;
501 
502  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
503  ACL_CREATE);
504  if (aclresult != ACLCHECK_OK)
505  aclcheck_error(aclresult, OBJECT_SCHEMA,
506  get_namespace_name(namespaceId));
507  }
508 
509  /*
510  * Select tablespace to use. If not specified, use default tablespace
511  * (which may in turn default to database's default).
512  */
513  if (stmt->tableSpace)
514  {
515  tablespaceId = get_tablespace_oid(stmt->tableSpace, false);
516  }
517  else
518  {
519  tablespaceId = GetDefaultTablespace(rel->rd_rel->relpersistence);
520  /* note InvalidOid is OK in this case */
521  }
522 
523  /* Check tablespace permissions */
524  if (check_rights &&
525  OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
526  {
527  AclResult aclresult;
528 
529  aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
530  ACL_CREATE);
531  if (aclresult != ACLCHECK_OK)
533  get_tablespace_name(tablespaceId));
534  }
535 
536  /*
537  * Force shared indexes into the pg_global tablespace. This is a bit of a
538  * hack but seems simpler than marking them in the BKI commands. On the
539  * other hand, if it's not shared, don't allow it to be placed there.
540  */
541  if (rel->rd_rel->relisshared)
542  tablespaceId = GLOBALTABLESPACE_OID;
543  else if (tablespaceId == GLOBALTABLESPACE_OID)
544  ereport(ERROR,
545  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
546  errmsg("only shared relations can be placed in pg_global tablespace")));
547 
548  /*
549  * Choose the index column names.
550  */
551  indexColNames = ChooseIndexColumnNames(allIndexParams);
552 
553  /*
554  * Select name for index if caller didn't specify
555  */
556  indexRelationName = stmt->idxname;
557  if (indexRelationName == NULL)
558  indexRelationName = ChooseIndexName(RelationGetRelationName(rel),
559  namespaceId,
560  indexColNames,
561  stmt->excludeOpNames,
562  stmt->primary,
563  stmt->isconstraint);
564 
565  /*
566  * look up the access method, verify it can handle the requested features
567  */
568  accessMethodName = stmt->accessMethod;
569  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
570  if (!HeapTupleIsValid(tuple))
571  {
572  /*
573  * Hack to provide more-or-less-transparent updating of old RTREE
574  * indexes to GiST: if RTREE is requested and not found, use GIST.
575  */
576  if (strcmp(accessMethodName, "rtree") == 0)
577  {
578  ereport(NOTICE,
579  (errmsg("substituting access method \"gist\" for obsolete method \"rtree\"")));
580  accessMethodName = "gist";
581  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
582  }
583 
584  if (!HeapTupleIsValid(tuple))
585  ereport(ERROR,
586  (errcode(ERRCODE_UNDEFINED_OBJECT),
587  errmsg("access method \"%s\" does not exist",
588  accessMethodName)));
589  }
590  accessMethodId = HeapTupleGetOid(tuple);
591  accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
592  amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
593 
594  if (stmt->unique && !amRoutine->amcanunique)
595  ereport(ERROR,
596  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
597  errmsg("access method \"%s\" does not support unique indexes",
598  accessMethodName)));
599  if (list_length(stmt->indexIncludingParams) > 0 && !amRoutine->amcaninclude)
600  ereport(ERROR,
601  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
602  errmsg("access method \"%s\" does not support included columns",
603  accessMethodName)));
604  if (numberOfAttributes > 1 && !amRoutine->amcanmulticol)
605  ereport(ERROR,
606  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
607  errmsg("access method \"%s\" does not support multicolumn indexes",
608  accessMethodName)));
609  if (stmt->excludeOpNames && amRoutine->amgettuple == NULL)
610  ereport(ERROR,
611  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
612  errmsg("access method \"%s\" does not support exclusion constraints",
613  accessMethodName)));
614 
615  amcanorder = amRoutine->amcanorder;
616  amoptions = amRoutine->amoptions;
617 
618  pfree(amRoutine);
619  ReleaseSysCache(tuple);
620 
621  /*
622  * Validate predicate, if given
623  */
624  if (stmt->whereClause)
625  CheckPredicate((Expr *) stmt->whereClause);
626 
627  /*
628  * Parse AM-specific options, convert to text array form, validate.
629  */
630  reloptions = transformRelOptions((Datum) 0, stmt->options,
631  NULL, NULL, false, false);
632 
633  (void) index_reloptions(amoptions, reloptions, true);
634 
635  /*
636  * Prepare arguments for index_create, primarily an IndexInfo structure.
637  * Note that ii_Predicate must be in implicit-AND format.
638  */
639  indexInfo = makeNode(IndexInfo);
640  indexInfo->ii_NumIndexAttrs = numberOfAttributes;
641  indexInfo->ii_NumIndexKeyAttrs = numberOfKeyAttributes;
642  indexInfo->ii_Expressions = NIL; /* for now */
643  indexInfo->ii_ExpressionsState = NIL;
644  indexInfo->ii_Predicate = make_ands_implicit((Expr *) stmt->whereClause);
645  indexInfo->ii_PredicateState = NULL;
646  indexInfo->ii_ExclusionOps = NULL;
647  indexInfo->ii_ExclusionProcs = NULL;
648  indexInfo->ii_ExclusionStrats = NULL;
649  indexInfo->ii_Unique = stmt->unique;
650  /* In a concurrent build, mark it not-ready-for-inserts */
651  indexInfo->ii_ReadyForInserts = !stmt->concurrent;
652  indexInfo->ii_Concurrent = stmt->concurrent;
653  indexInfo->ii_BrokenHotChain = false;
654  indexInfo->ii_ParallelWorkers = 0;
655  indexInfo->ii_Am = accessMethodId;
656  indexInfo->ii_AmCache = NULL;
657  indexInfo->ii_Context = CurrentMemoryContext;
658 
659  typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
660  collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
661  classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
662  coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16));
663  ComputeIndexAttrs(indexInfo,
664  typeObjectId, collationObjectId, classObjectId,
665  coloptions, allIndexParams,
666  stmt->excludeOpNames, relationId,
667  accessMethodName, accessMethodId,
668  amcanorder, stmt->isconstraint);
669 
670  /*
671  * Extra checks when creating a PRIMARY KEY index.
672  */
673  if (stmt->primary)
674  index_check_primary_key(rel, indexInfo, is_alter_table);
675 
676  /*
677  * If this table is partitioned and we're creating a unique index or a
678  * primary key, make sure that the indexed columns are part of the
679  * partition key. Otherwise it would be possible to violate uniqueness by
680  * putting values that ought to be unique in different partitions.
681  *
682  * We could lift this limitation if we had global indexes, but those have
683  * their own problems, so this is a useful feature combination.
684  */
685  if (partitioned && (stmt->unique || stmt->primary))
686  {
687  PartitionKey key = rel->rd_partkey;
688  int i;
689 
690  /*
691  * A partitioned table can have unique indexes, as long as all the
692  * columns in the partition key appear in the unique key. A
693  * partition-local index can enforce global uniqueness iff the PK
694  * value completely determines the partition that a row is in.
695  *
696  * Thus, verify that all the columns in the partition key appear in
697  * the unique key definition.
698  */
699  for (i = 0; i < key->partnatts; i++)
700  {
701  bool found = false;
702  int j;
703  const char *constraint_type;
704 
705  if (stmt->primary)
706  constraint_type = "PRIMARY KEY";
707  else if (stmt->unique)
708  constraint_type = "UNIQUE";
709  else if (stmt->excludeOpNames != NIL)
710  constraint_type = "EXCLUDE";
711  else
712  {
713  elog(ERROR, "unknown constraint type");
714  constraint_type = NULL; /* keep compiler quiet */
715  }
716 
717  /*
718  * It may be possible to support UNIQUE constraints when partition
719  * keys are expressions, but is it worth it? Give up for now.
720  */
721  if (key->partattrs[i] == 0)
722  ereport(ERROR,
723  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
724  errmsg("unsupported %s constraint with partition key definition",
725  constraint_type),
726  errdetail("%s constraints cannot be used when partition keys include expressions.",
727  constraint_type)));
728 
729  for (j = 0; j < indexInfo->ii_NumIndexAttrs; j++)
730  {
731  if (key->partattrs[i] == indexInfo->ii_IndexAttrNumbers[j])
732  {
733  found = true;
734  break;
735  }
736  }
737  if (!found)
738  {
739  Form_pg_attribute att;
740 
741  att = TupleDescAttr(RelationGetDescr(rel), key->partattrs[i] - 1);
742  ereport(ERROR,
743  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
744  errmsg("insufficient columns in %s constraint definition",
745  constraint_type),
746  errdetail("%s constraint on table \"%s\" lacks column \"%s\" which is part of the partition key.",
747  constraint_type, RelationGetRelationName(rel),
748  NameStr(att->attname))));
749  }
750  }
751  }
752 
753 
754  /*
755  * We disallow indexes on system columns other than OID. They would not
756  * necessarily get updated correctly, and they don't seem useful anyway.
757  */
758  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
759  {
760  AttrNumber attno = indexInfo->ii_IndexAttrNumbers[i];
761 
762  if (attno < 0 && attno != ObjectIdAttributeNumber)
763  ereport(ERROR,
764  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
765  errmsg("index creation on system columns is not supported")));
766  }
767 
768  /*
769  * Also check for system columns used in expressions or predicates.
770  */
771  if (indexInfo->ii_Expressions || indexInfo->ii_Predicate)
772  {
773  Bitmapset *indexattrs = NULL;
774 
775  pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs);
776  pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs);
777 
778  for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
779  {
780  if (i != ObjectIdAttributeNumber &&
782  indexattrs))
783  ereport(ERROR,
784  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
785  errmsg("index creation on system columns is not supported")));
786  }
787  }
788 
789  /*
790  * Report index creation if appropriate (delay this till after most of the
791  * error checks)
792  */
793  if (stmt->isconstraint && !quiet)
794  {
795  const char *constraint_type;
796 
797  if (stmt->primary)
798  constraint_type = "PRIMARY KEY";
799  else if (stmt->unique)
800  constraint_type = "UNIQUE";
801  else if (stmt->excludeOpNames != NIL)
802  constraint_type = "EXCLUDE";
803  else
804  {
805  elog(ERROR, "unknown constraint type");
806  constraint_type = NULL; /* keep compiler quiet */
807  }
808 
809  ereport(DEBUG1,
810  (errmsg("%s %s will create implicit index \"%s\" for table \"%s\"",
811  is_alter_table ? "ALTER TABLE / ADD" : "CREATE TABLE /",
812  constraint_type,
813  indexRelationName, RelationGetRelationName(rel))));
814  }
815 
816  /*
817  * A valid stmt->oldNode implies that we already have a built form of the
818  * index. The caller should also decline any index build.
819  */
820  Assert(!OidIsValid(stmt->oldNode) || (skip_build && !stmt->concurrent));
821 
822  /*
823  * Make the catalog entries for the index, including constraints. This
824  * step also actually builds the index, except if caller requested not to
825  * or in concurrent mode, in which case it'll be done later, or doing a
826  * partitioned index (because those don't have storage).
827  */
828  flags = constr_flags = 0;
829  if (stmt->isconstraint)
831  if (skip_build || stmt->concurrent || partitioned)
832  flags |= INDEX_CREATE_SKIP_BUILD;
833  if (stmt->if_not_exists)
835  if (stmt->concurrent)
836  flags |= INDEX_CREATE_CONCURRENT;
837  if (partitioned)
838  flags |= INDEX_CREATE_PARTITIONED;
839  if (stmt->primary)
840  flags |= INDEX_CREATE_IS_PRIMARY;
841  if (partitioned && stmt->relation && !stmt->relation->inh)
842  flags |= INDEX_CREATE_INVALID;
843 
844  if (stmt->deferrable)
845  constr_flags |= INDEX_CONSTR_CREATE_DEFERRABLE;
846  if (stmt->initdeferred)
847  constr_flags |= INDEX_CONSTR_CREATE_INIT_DEFERRED;
848 
849  indexRelationId =
850  index_create(rel, indexRelationName, indexRelationId, parentIndexId,
851  parentConstraintId,
852  stmt->oldNode, indexInfo, indexColNames,
853  accessMethodId, tablespaceId,
854  collationObjectId, classObjectId,
855  coloptions, reloptions,
856  flags, constr_flags,
857  allowSystemTableMods, !check_rights,
858  &createdConstraintId);
859 
860  ObjectAddressSet(address, RelationRelationId, indexRelationId);
861 
862  if (!OidIsValid(indexRelationId))
863  {
864  heap_close(rel, NoLock);
865  return address;
866  }
867 
868  /* Add any requested comment */
869  if (stmt->idxcomment != NULL)
870  CreateComments(indexRelationId, RelationRelationId, 0,
871  stmt->idxcomment);
872 
873  if (partitioned)
874  {
875  /*
876  * Unless caller specified to skip this step (via ONLY), process each
877  * partition to make sure they all contain a corresponding index.
878  *
879  * If we're called internally (no stmt->relation), recurse always.
880  */
881  if (!stmt->relation || stmt->relation->inh)
882  {
883  PartitionDesc partdesc = RelationGetPartitionDesc(rel);
884  int nparts = partdesc->nparts;
885  Oid *part_oids = palloc(sizeof(Oid) * nparts);
886  bool invalidate_parent = false;
887  TupleDesc parentDesc;
888  Oid *opfamOids;
889 
890  memcpy(part_oids, partdesc->oids, sizeof(Oid) * nparts);
891 
892  parentDesc = CreateTupleDescCopy(RelationGetDescr(rel));
893  opfamOids = palloc(sizeof(Oid) * numberOfKeyAttributes);
894  for (i = 0; i < numberOfKeyAttributes; i++)
895  opfamOids[i] = get_opclass_family(classObjectId[i]);
896 
897  heap_close(rel, NoLock);
898 
899  /*
900  * For each partition, scan all existing indexes; if one matches
901  * our index definition and is not already attached to some other
902  * parent index, attach it to the one we just created.
903  *
904  * If none matches, build a new index by calling ourselves
905  * recursively with the same options (except for the index name).
906  */
907  for (i = 0; i < nparts; i++)
908  {
909  Oid childRelid = part_oids[i];
910  Relation childrel;
911  List *childidxs;
912  ListCell *cell;
913  AttrNumber *attmap;
914  bool found = false;
915  int maplen;
916 
917  childrel = heap_open(childRelid, lockmode);
918  childidxs = RelationGetIndexList(childrel);
919  attmap =
921  parentDesc,
922  gettext_noop("could not convert row type"));
923  maplen = parentDesc->natts;
924 
925 
926  foreach(cell, childidxs)
927  {
928  Oid cldidxid = lfirst_oid(cell);
929  Relation cldidx;
930  IndexInfo *cldIdxInfo;
931 
932  /* this index is already partition of another one */
933  if (has_superclass(cldidxid))
934  continue;
935 
936  cldidx = index_open(cldidxid, lockmode);
937  cldIdxInfo = BuildIndexInfo(cldidx);
938  if (CompareIndexInfo(cldIdxInfo, indexInfo,
939  cldidx->rd_indcollation,
940  collationObjectId,
941  cldidx->rd_opfamily,
942  opfamOids,
943  attmap, maplen))
944  {
945  Oid cldConstrOid = InvalidOid;
946 
947  /*
948  * Found a match.
949  *
950  * If this index is being created in the parent
951  * because of a constraint, then the child needs to
952  * have a constraint also, so look for one. If there
953  * is no such constraint, this index is no good, so
954  * keep looking.
955  */
956  if (createdConstraintId != InvalidOid)
957  {
958  cldConstrOid =
960  cldidxid);
961  if (cldConstrOid == InvalidOid)
962  {
963  index_close(cldidx, lockmode);
964  continue;
965  }
966  }
967 
968  /* Attach index to parent and we're done. */
969  IndexSetParentIndex(cldidx, indexRelationId);
970  if (createdConstraintId != InvalidOid)
971  ConstraintSetParentConstraint(cldConstrOid,
972  createdConstraintId);
973 
974  if (!IndexIsValid(cldidx->rd_index))
975  invalidate_parent = true;
976 
977  found = true;
978  /* keep lock till commit */
979  index_close(cldidx, NoLock);
980  break;
981  }
982 
983  index_close(cldidx, lockmode);
984  }
985 
986  list_free(childidxs);
987  heap_close(childrel, NoLock);
988 
989  /*
990  * If no matching index was found, create our own.
991  */
992  if (!found)
993  {
994  IndexStmt *childStmt = copyObject(stmt);
995  bool found_whole_row;
996 
997  childStmt->whereClause =
998  map_variable_attnos(stmt->whereClause, 1, 0,
999  attmap, maplen,
1000  InvalidOid, &found_whole_row);
1001  if (found_whole_row)
1002  elog(ERROR, "cannot convert whole-row table reference");
1003 
1004  childStmt->idxname = NULL;
1005  childStmt->relationId = childRelid;
1006  DefineIndex(childRelid, childStmt,
1007  InvalidOid, /* no predefined OID */
1008  indexRelationId, /* this is our child */
1009  createdConstraintId,
1010  is_alter_table, check_rights, check_not_in_use,
1011  false, quiet);
1012  }
1013 
1014  pfree(attmap);
1015  }
1016 
1017  /*
1018  * The pg_index row we inserted for this index was marked
1019  * indisvalid=true. But if we attached an existing index that is
1020  * invalid, this is incorrect, so update our row to invalid too.
1021  */
1022  if (invalidate_parent)
1023  {
1024  Relation pg_index = heap_open(IndexRelationId, RowExclusiveLock);
1025  HeapTuple tup,
1026  newtup;
1027 
1029  ObjectIdGetDatum(indexRelationId));
1030  if (!tup)
1031  elog(ERROR, "cache lookup failed for index %u",
1032  indexRelationId);
1033  newtup = heap_copytuple(tup);
1034  ((Form_pg_index) GETSTRUCT(newtup))->indisvalid = false;
1035  CatalogTupleUpdate(pg_index, &tup->t_self, newtup);
1036  ReleaseSysCache(tup);
1037  heap_close(pg_index, RowExclusiveLock);
1038  heap_freetuple(newtup);
1039  }
1040  }
1041  else
1042  heap_close(rel, NoLock);
1043 
1044  /*
1045  * Indexes on partitioned tables are not themselves built, so we're
1046  * done here.
1047  */
1048  return address;
1049  }
1050 
1051  if (!stmt->concurrent)
1052  {
1053  /* Close the heap and we're done, in the non-concurrent case */
1054  heap_close(rel, NoLock);
1055  return address;
1056  }
1057 
1058  /* save lockrelid and locktag for below, then close rel */
1059  heaprelid = rel->rd_lockInfo.lockRelId;
1060  SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
1061  heap_close(rel, NoLock);
1062 
1063  /*
1064  * For a concurrent build, it's important to make the catalog entries
1065  * visible to other transactions before we start to build the index. That
1066  * will prevent them from making incompatible HOT updates. The new index
1067  * will be marked not indisready and not indisvalid, so that no one else
1068  * tries to either insert into it or use it for queries.
1069  *
1070  * We must commit our current transaction so that the index becomes
1071  * visible; then start another. Note that all the data structures we just
1072  * built are lost in the commit. The only data we keep past here are the
1073  * relation IDs.
1074  *
1075  * Before committing, get a session-level lock on the table, to ensure
1076  * that neither it nor the index can be dropped before we finish. This
1077  * cannot block, even if someone else is waiting for access, because we
1078  * already have the same lock within our transaction.
1079  *
1080  * Note: we don't currently bother with a session lock on the index,
1081  * because there are no operations that could change its state while we
1082  * hold lock on the parent table. This might need to change later.
1083  */
1085 
1089 
1090  /*
1091  * Phase 2 of concurrent index build (see comments for validate_index()
1092  * for an overview of how this works)
1093  *
1094  * Now we must wait until no running transaction could have the table open
1095  * with the old list of indexes. Use ShareLock to consider running
1096  * transactions that hold locks that permit writing to the table. Note we
1097  * do not need to worry about xacts that open the table for writing after
1098  * this point; they will see the new index when they open it.
1099  *
1100  * Note: the reason we use actual lock acquisition here, rather than just
1101  * checking the ProcArray and sleeping, is that deadlock is possible if
1102  * one of the transactions in question is blocked trying to acquire an
1103  * exclusive lock on our table. The lock code will detect deadlock and
1104  * error out properly.
1105  */
1106  WaitForLockers(heaplocktag, ShareLock);
1107 
1108  /*
1109  * At this moment we are sure that there are no transactions with the
1110  * table open for write that don't have this new index in their list of
1111  * indexes. We have waited out all the existing transactions and any new
1112  * transaction will have the new index in its list, but the index is still
1113  * marked as "not-ready-for-inserts". The index is consulted while
1114  * deciding HOT-safety though. This arrangement ensures that no new HOT
1115  * chains can be created where the new tuple and the old tuple in the
1116  * chain have different index keys.
1117  *
1118  * We now take a new snapshot, and build the index using all tuples that
1119  * are visible in this snapshot. We can be sure that any HOT updates to
1120  * these tuples will be compatible with the index, since any updates made
1121  * by transactions that didn't know about the index are now committed or
1122  * rolled back. Thus, each visible tuple is either the end of its
1123  * HOT-chain or the extension of the chain is HOT-safe for this index.
1124  */
1125 
1126  /* Open and lock the parent heap relation */
1128 
1129  /* And the target index relation */
1130  indexRelation = index_open(indexRelationId, RowExclusiveLock);
1131 
1132  /* Set ActiveSnapshot since functions in the indexes may need it */
1134 
1135  /* We have to re-build the IndexInfo struct, since it was lost in commit */
1136  indexInfo = BuildIndexInfo(indexRelation);
1137  Assert(!indexInfo->ii_ReadyForInserts);
1138  indexInfo->ii_Concurrent = true;
1139  indexInfo->ii_BrokenHotChain = false;
1140 
1141  /* Now build the index */
1142  index_build(rel, indexRelation, indexInfo, stmt->primary, false, true);
1143 
1144  /* Close both the relations, but keep the locks */
1145  heap_close(rel, NoLock);
1146  index_close(indexRelation, NoLock);
1147 
1148  /*
1149  * Update the pg_index row to mark the index as ready for inserts. Once we
1150  * commit this transaction, any new transactions that open the table must
1151  * insert new entries into the index for insertions and non-HOT updates.
1152  */
1154 
1155  /* we can do away with our snapshot */
1157 
1158  /*
1159  * Commit this transaction to make the indisready update visible.
1160  */
1163 
1164  /*
1165  * Phase 3 of concurrent index build
1166  *
1167  * We once again wait until no transaction can have the table open with
1168  * the index marked as read-only for updates.
1169  */
1170  WaitForLockers(heaplocktag, ShareLock);
1171 
1172  /*
1173  * Now take the "reference snapshot" that will be used by validate_index()
1174  * to filter candidate tuples. Beware! There might still be snapshots in
1175  * use that treat some transaction as in-progress that our reference
1176  * snapshot treats as committed. If such a recently-committed transaction
1177  * deleted tuples in the table, we will not include them in the index; yet
1178  * those transactions which see the deleting one as still-in-progress will
1179  * expect such tuples to be there once we mark the index as valid.
1180  *
1181  * We solve this by waiting for all endangered transactions to exit before
1182  * we mark the index as valid.
1183  *
1184  * We also set ActiveSnapshot to this snap, since functions in indexes may
1185  * need a snapshot.
1186  */
1188  PushActiveSnapshot(snapshot);
1189 
1190  /*
1191  * Scan the index and the heap, insert any missing index entries.
1192  */
1193  validate_index(relationId, indexRelationId, snapshot);
1194 
1195  /*
1196  * Drop the reference snapshot. We must do this before waiting out other
1197  * snapshot holders, else we will deadlock against other processes also
1198  * doing CREATE INDEX CONCURRENTLY, which would see our snapshot as one
1199  * they must wait for. But first, save the snapshot's xmin to use as
1200  * limitXmin for GetCurrentVirtualXIDs().
1201  */
1202  limitXmin = snapshot->xmin;
1203 
1205  UnregisterSnapshot(snapshot);
1206 
1207  /*
1208  * The snapshot subsystem could still contain registered snapshots that
1209  * are holding back our process's advertised xmin; in particular, if
1210  * default_transaction_isolation = serializable, there is a transaction
1211  * snapshot that is still active. The CatalogSnapshot is likewise a
1212  * hazard. To ensure no deadlocks, we must commit and start yet another
1213  * transaction, and do our wait before any snapshot has been taken in it.
1214  */
1217 
1218  /* We should now definitely not be advertising any xmin. */
1220 
1221  /*
1222  * The index is now valid in the sense that it contains all currently
1223  * interesting tuples. But since it might not contain tuples deleted just
1224  * before the reference snap was taken, we have to wait out any
1225  * transactions that might have older snapshots. Obtain a list of VXIDs
1226  * of such transactions, and wait for them individually.
1227  *
1228  * We can exclude any running transactions that have xmin > the xmin of
1229  * our reference snapshot; their oldest snapshot must be newer than ours.
1230  * We can also exclude any transactions that have xmin = zero, since they
1231  * evidently have no live snapshot at all (and any one they might be in
1232  * process of taking is certainly newer than ours). Transactions in other
1233  * DBs can be ignored too, since they'll never even be able to see this
1234  * index.
1235  *
1236  * We can also exclude autovacuum processes and processes running manual
1237  * lazy VACUUMs, because they won't be fazed by missing index entries
1238  * either. (Manual ANALYZEs, however, can't be excluded because they
1239  * might be within transactions that are going to do arbitrary operations
1240  * later.)
1241  *
1242  * Also, GetCurrentVirtualXIDs never reports our own vxid, so we need not
1243  * check for that.
1244  *
1245  * If a process goes idle-in-transaction with xmin zero, we do not need to
1246  * wait for it anymore, per the above argument. We do not have the
1247  * infrastructure right now to stop waiting if that happens, but we can at
1248  * least avoid the folly of waiting when it is idle at the time we would
1249  * begin to wait. We do this by repeatedly rechecking the output of
1250  * GetCurrentVirtualXIDs. If, during any iteration, a particular vxid
1251  * doesn't show up in the output, we know we can forget about it.
1252  */
1253  old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
1255  &n_old_snapshots);
1256 
1257  for (i = 0; i < n_old_snapshots; i++)
1258  {
1259  if (!VirtualTransactionIdIsValid(old_snapshots[i]))
1260  continue; /* found uninteresting in previous cycle */
1261 
1262  if (i > 0)
1263  {
1264  /* see if anything's changed ... */
1265  VirtualTransactionId *newer_snapshots;
1266  int n_newer_snapshots;
1267  int j;
1268  int k;
1269 
1270  newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
1271  true, false,
1273  &n_newer_snapshots);
1274  for (j = i; j < n_old_snapshots; j++)
1275  {
1276  if (!VirtualTransactionIdIsValid(old_snapshots[j]))
1277  continue; /* found uninteresting in previous cycle */
1278  for (k = 0; k < n_newer_snapshots; k++)
1279  {
1280  if (VirtualTransactionIdEquals(old_snapshots[j],
1281  newer_snapshots[k]))
1282  break;
1283  }
1284  if (k >= n_newer_snapshots) /* not there anymore */
1285  SetInvalidVirtualTransactionId(old_snapshots[j]);
1286  }
1287  pfree(newer_snapshots);
1288  }
1289 
1290  if (VirtualTransactionIdIsValid(old_snapshots[i]))
1291  VirtualXactLock(old_snapshots[i], true);
1292  }
1293 
1294  /*
1295  * Index can now be marked valid -- update its pg_index entry
1296  */
1298 
1299  /*
1300  * The pg_index update will cause backends (including this one) to update
1301  * relcache entries for the index itself, but we should also send a
1302  * relcache inval on the parent table to force replanning of cached plans.
1303  * Otherwise existing sessions might fail to use the new index where it
1304  * would be useful. (Note that our earlier commits did not create reasons
1305  * to replan; so relcache flush on the index itself was sufficient.)
1306  */
1308 
1309  /*
1310  * Last thing to do is release the session-level lock on the parent table.
1311  */
1313 
1314  return address;
1315 }
1316 
1317 
1318 /*
1319  * CheckMutability
1320  * Test whether given expression is mutable
1321  */
1322 static bool
1324 {
1325  /*
1326  * First run the expression through the planner. This has a couple of
1327  * important consequences. First, function default arguments will get
1328  * inserted, which may affect volatility (consider "default now()").
1329  * Second, inline-able functions will get inlined, which may allow us to
1330  * conclude that the function is really less volatile than it's marked. As
1331  * an example, polymorphic functions must be marked with the most volatile
1332  * behavior that they have for any input type, but once we inline the
1333  * function we may be able to conclude that it's not so volatile for the
1334  * particular input type we're dealing with.
1335  *
1336  * We assume here that expression_planner() won't scribble on its input.
1337  */
1338  expr = expression_planner(expr);
1339 
1340  /* Now we can search for non-immutable functions */
1341  return contain_mutable_functions((Node *) expr);
1342 }
1343 
1344 
1345 /*
1346  * CheckPredicate
1347  * Checks that the given partial-index predicate is valid.
1348  *
1349  * This used to also constrain the form of the predicate to forms that
1350  * indxpath.c could do something with. However, that seems overly
1351  * restrictive. One useful application of partial indexes is to apply
1352  * a UNIQUE constraint across a subset of a table, and in that scenario
1353  * any evaluable predicate will work. So accept any predicate here
1354  * (except ones requiring a plan), and let indxpath.c fend for itself.
1355  */
1356 static void
1358 {
1359  /*
1360  * transformExpr() should have already rejected subqueries, aggregates,
1361  * and window functions, based on the EXPR_KIND_ for a predicate.
1362  */
1363 
1364  /*
1365  * A predicate using mutable functions is probably wrong, for the same
1366  * reasons that we don't allow an index expression to use one.
1367  */
1368  if (CheckMutability(predicate))
1369  ereport(ERROR,
1370  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1371  errmsg("functions in index predicate must be marked IMMUTABLE")));
1372 }
1373 
1374 /*
1375  * Compute per-index-column information, including indexed column numbers
1376  * or index expressions, opclasses, and indoptions. Note, all output vectors
1377  * should be allocated for all columns, including "including" ones.
1378  */
1379 static void
1381  Oid *typeOidP,
1382  Oid *collationOidP,
1383  Oid *classOidP,
1384  int16 *colOptionP,
1385  List *attList, /* list of IndexElem's */
1386  List *exclusionOpNames,
1387  Oid relId,
1388  const char *accessMethodName,
1389  Oid accessMethodId,
1390  bool amcanorder,
1391  bool isconstraint)
1392 {
1393  ListCell *nextExclOp;
1394  ListCell *lc;
1395  int attn;
1396  int nkeycols = indexInfo->ii_NumIndexKeyAttrs;
1397 
1398  /* Allocate space for exclusion operator info, if needed */
1399  if (exclusionOpNames)
1400  {
1401  Assert(list_length(exclusionOpNames) == nkeycols);
1402  indexInfo->ii_ExclusionOps = (Oid *) palloc(sizeof(Oid) * nkeycols);
1403  indexInfo->ii_ExclusionProcs = (Oid *) palloc(sizeof(Oid) * nkeycols);
1404  indexInfo->ii_ExclusionStrats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
1405  nextExclOp = list_head(exclusionOpNames);
1406  }
1407  else
1408  nextExclOp = NULL;
1409 
1410  /*
1411  * process attributeList
1412  */
1413  attn = 0;
1414  foreach(lc, attList)
1415  {
1416  IndexElem *attribute = (IndexElem *) lfirst(lc);
1417  Oid atttype;
1418  Oid attcollation;
1419 
1420  /*
1421  * Process the column-or-expression to be indexed.
1422  */
1423  if (attribute->name != NULL)
1424  {
1425  /* Simple index attribute */
1426  HeapTuple atttuple;
1427  Form_pg_attribute attform;
1428 
1429  Assert(attribute->expr == NULL);
1430  atttuple = SearchSysCacheAttName(relId, attribute->name);
1431  if (!HeapTupleIsValid(atttuple))
1432  {
1433  /* difference in error message spellings is historical */
1434  if (isconstraint)
1435  ereport(ERROR,
1436  (errcode(ERRCODE_UNDEFINED_COLUMN),
1437  errmsg("column \"%s\" named in key does not exist",
1438  attribute->name)));
1439  else
1440  ereport(ERROR,
1441  (errcode(ERRCODE_UNDEFINED_COLUMN),
1442  errmsg("column \"%s\" does not exist",
1443  attribute->name)));
1444  }
1445  attform = (Form_pg_attribute) GETSTRUCT(atttuple);
1446  indexInfo->ii_IndexAttrNumbers[attn] = attform->attnum;
1447  atttype = attform->atttypid;
1448  attcollation = attform->attcollation;
1449  ReleaseSysCache(atttuple);
1450  }
1451  else
1452  {
1453  /* Index expression */
1454  Node *expr = attribute->expr;
1455 
1456  Assert(expr != NULL);
1457 
1458  if (attn >= nkeycols)
1459  ereport(ERROR,
1460  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1461  errmsg("expressions are not supported in included columns")));
1462  atttype = exprType(expr);
1463  attcollation = exprCollation(expr);
1464 
1465  /*
1466  * Strip any top-level COLLATE clause. This ensures that we treat
1467  * "x COLLATE y" and "(x COLLATE y)" alike.
1468  */
1469  while (IsA(expr, CollateExpr))
1470  expr = (Node *) ((CollateExpr *) expr)->arg;
1471 
1472  if (IsA(expr, Var) &&
1473  ((Var *) expr)->varattno != InvalidAttrNumber)
1474  {
1475  /*
1476  * User wrote "(column)" or "(column COLLATE something)".
1477  * Treat it like simple attribute anyway.
1478  */
1479  indexInfo->ii_IndexAttrNumbers[attn] = ((Var *) expr)->varattno;
1480  }
1481  else
1482  {
1483  indexInfo->ii_IndexAttrNumbers[attn] = 0; /* marks expression */
1484  indexInfo->ii_Expressions = lappend(indexInfo->ii_Expressions,
1485  expr);
1486 
1487  /*
1488  * transformExpr() should have already rejected subqueries,
1489  * aggregates, and window functions, based on the EXPR_KIND_
1490  * for an index expression.
1491  */
1492 
1493  /*
1494  * An expression using mutable functions is probably wrong,
1495  * since if you aren't going to get the same result for the
1496  * same data every time, it's not clear what the index entries
1497  * mean at all.
1498  */
1499  if (CheckMutability((Expr *) expr))
1500  ereport(ERROR,
1501  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1502  errmsg("functions in index expression must be marked IMMUTABLE")));
1503  }
1504  }
1505 
1506  typeOidP[attn] = atttype;
1507 
1508  /*
1509  * Included columns have no collation, no opclass and no ordering
1510  * options.
1511  */
1512  if (attn >= nkeycols)
1513  {
1514  if (attribute->collation)
1515  ereport(ERROR,
1516  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1517  errmsg("including column does not support a collation")));
1518  if (attribute->opclass)
1519  ereport(ERROR,
1520  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1521  errmsg("including column does not support an operator class")));
1522  if (attribute->ordering != SORTBY_DEFAULT)
1523  ereport(ERROR,
1524  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1525  errmsg("including column does not support ASC/DESC options")));
1526  if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
1527  ereport(ERROR,
1528  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1529  errmsg("including column does not support NULLS FIRST/LAST options")));
1530 
1531  classOidP[attn] = InvalidOid;
1532  colOptionP[attn] = 0;
1533  collationOidP[attn] = InvalidOid;
1534  attn++;
1535 
1536  continue;
1537  }
1538 
1539  /*
1540  * Apply collation override if any
1541  */
1542  if (attribute->collation)
1543  attcollation = get_collation_oid(attribute->collation, false);
1544 
1545  /*
1546  * Check we have a collation iff it's a collatable type. The only
1547  * expected failures here are (1) COLLATE applied to a noncollatable
1548  * type, or (2) index expression had an unresolved collation. But we
1549  * might as well code this to be a complete consistency check.
1550  */
1551  if (type_is_collatable(atttype))
1552  {
1553  if (!OidIsValid(attcollation))
1554  ereport(ERROR,
1555  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1556  errmsg("could not determine which collation to use for index expression"),
1557  errhint("Use the COLLATE clause to set the collation explicitly.")));
1558  }
1559  else
1560  {
1561  if (OidIsValid(attcollation))
1562  ereport(ERROR,
1563  (errcode(ERRCODE_DATATYPE_MISMATCH),
1564  errmsg("collations are not supported by type %s",
1565  format_type_be(atttype))));
1566  }
1567 
1568  collationOidP[attn] = attcollation;
1569 
1570  /*
1571  * Identify the opclass to use.
1572  */
1573  classOidP[attn] = ResolveOpClass(attribute->opclass,
1574  atttype,
1575  accessMethodName,
1576  accessMethodId);
1577 
1578  /*
1579  * Identify the exclusion operator, if any.
1580  */
1581  if (nextExclOp)
1582  {
1583  List *opname = (List *) lfirst(nextExclOp);
1584  Oid opid;
1585  Oid opfamily;
1586  int strat;
1587 
1588  /*
1589  * Find the operator --- it must accept the column datatype
1590  * without runtime coercion (but binary compatibility is OK)
1591  */
1592  opid = compatible_oper_opid(opname, atttype, atttype, false);
1593 
1594  /*
1595  * Only allow commutative operators to be used in exclusion
1596  * constraints. If X conflicts with Y, but Y does not conflict
1597  * with X, bad things will happen.
1598  */
1599  if (get_commutator(opid) != opid)
1600  ereport(ERROR,
1601  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1602  errmsg("operator %s is not commutative",
1603  format_operator(opid)),
1604  errdetail("Only commutative operators can be used in exclusion constraints.")));
1605 
1606  /*
1607  * Operator must be a member of the right opfamily, too
1608  */
1609  opfamily = get_opclass_family(classOidP[attn]);
1610  strat = get_op_opfamily_strategy(opid, opfamily);
1611  if (strat == 0)
1612  {
1613  HeapTuple opftuple;
1614  Form_pg_opfamily opfform;
1615 
1616  /*
1617  * attribute->opclass might not explicitly name the opfamily,
1618  * so fetch the name of the selected opfamily for use in the
1619  * error message.
1620  */
1621  opftuple = SearchSysCache1(OPFAMILYOID,
1622  ObjectIdGetDatum(opfamily));
1623  if (!HeapTupleIsValid(opftuple))
1624  elog(ERROR, "cache lookup failed for opfamily %u",
1625  opfamily);
1626  opfform = (Form_pg_opfamily) GETSTRUCT(opftuple);
1627 
1628  ereport(ERROR,
1629  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1630  errmsg("operator %s is not a member of operator family \"%s\"",
1631  format_operator(opid),
1632  NameStr(opfform->opfname)),
1633  errdetail("The exclusion operator must be related to the index operator class for the constraint.")));
1634  }
1635 
1636  indexInfo->ii_ExclusionOps[attn] = opid;
1637  indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
1638  indexInfo->ii_ExclusionStrats[attn] = strat;
1639  nextExclOp = lnext(nextExclOp);
1640  }
1641 
1642  /*
1643  * Set up the per-column options (indoption field). For now, this is
1644  * zero for any un-ordered index, while ordered indexes have DESC and
1645  * NULLS FIRST/LAST options.
1646  */
1647  colOptionP[attn] = 0;
1648  if (amcanorder)
1649  {
1650  /* default ordering is ASC */
1651  if (attribute->ordering == SORTBY_DESC)
1652  colOptionP[attn] |= INDOPTION_DESC;
1653  /* default null ordering is LAST for ASC, FIRST for DESC */
1654  if (attribute->nulls_ordering == SORTBY_NULLS_DEFAULT)
1655  {
1656  if (attribute->ordering == SORTBY_DESC)
1657  colOptionP[attn] |= INDOPTION_NULLS_FIRST;
1658  }
1659  else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
1660  colOptionP[attn] |= INDOPTION_NULLS_FIRST;
1661  }
1662  else
1663  {
1664  /* index AM does not support ordering */
1665  if (attribute->ordering != SORTBY_DEFAULT)
1666  ereport(ERROR,
1667  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1668  errmsg("access method \"%s\" does not support ASC/DESC options",
1669  accessMethodName)));
1670  if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
1671  ereport(ERROR,
1672  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1673  errmsg("access method \"%s\" does not support NULLS FIRST/LAST options",
1674  accessMethodName)));
1675  }
1676 
1677  attn++;
1678  }
1679 }
1680 
1681 /*
1682  * Resolve possibly-defaulted operator class specification
1683  *
1684  * Note: This is used to resolve operator class specification in index and
1685  * partition key definitions.
1686  */
1687 Oid
1688 ResolveOpClass(List *opclass, Oid attrType,
1689  const char *accessMethodName, Oid accessMethodId)
1690 {
1691  char *schemaname;
1692  char *opcname;
1693  HeapTuple tuple;
1694  Oid opClassId,
1695  opInputType;
1696 
1697  /*
1698  * Release 7.0 removed network_ops, timespan_ops, and datetime_ops, so we
1699  * ignore those opclass names so the default *_ops is used. This can be
1700  * removed in some later release. bjm 2000/02/07
1701  *
1702  * Release 7.1 removes lztext_ops, so suppress that too for a while. tgl
1703  * 2000/07/30
1704  *
1705  * Release 7.2 renames timestamp_ops to timestamptz_ops, so suppress that
1706  * too for awhile. I'm starting to think we need a better approach. tgl
1707  * 2000/10/01
1708  *
1709  * Release 8.0 removes bigbox_ops (which was dead code for a long while
1710  * anyway). tgl 2003/11/11
1711  */
1712  if (list_length(opclass) == 1)
1713  {
1714  char *claname = strVal(linitial(opclass));
1715 
1716  if (strcmp(claname, "network_ops") == 0 ||
1717  strcmp(claname, "timespan_ops") == 0 ||
1718  strcmp(claname, "datetime_ops") == 0 ||
1719  strcmp(claname, "lztext_ops") == 0 ||
1720  strcmp(claname, "timestamp_ops") == 0 ||
1721  strcmp(claname, "bigbox_ops") == 0)
1722  opclass = NIL;
1723  }
1724 
1725  if (opclass == NIL)
1726  {
1727  /* no operator class specified, so find the default */
1728  opClassId = GetDefaultOpClass(attrType, accessMethodId);
1729  if (!OidIsValid(opClassId))
1730  ereport(ERROR,
1731  (errcode(ERRCODE_UNDEFINED_OBJECT),
1732  errmsg("data type %s has no default operator class for access method \"%s\"",
1733  format_type_be(attrType), accessMethodName),
1734  errhint("You must specify an operator class for the index or define a default operator class for the data type.")));
1735  return opClassId;
1736  }
1737 
1738  /*
1739  * Specific opclass name given, so look up the opclass.
1740  */
1741 
1742  /* deconstruct the name list */
1743  DeconstructQualifiedName(opclass, &schemaname, &opcname);
1744 
1745  if (schemaname)
1746  {
1747  /* Look in specific schema only */
1748  Oid namespaceId;
1749 
1750  namespaceId = LookupExplicitNamespace(schemaname, false);
1751  tuple = SearchSysCache3(CLAAMNAMENSP,
1752  ObjectIdGetDatum(accessMethodId),
1753  PointerGetDatum(opcname),
1754  ObjectIdGetDatum(namespaceId));
1755  }
1756  else
1757  {
1758  /* Unqualified opclass name, so search the search path */
1759  opClassId = OpclassnameGetOpcid(accessMethodId, opcname);
1760  if (!OidIsValid(opClassId))
1761  ereport(ERROR,
1762  (errcode(ERRCODE_UNDEFINED_OBJECT),
1763  errmsg("operator class \"%s\" does not exist for access method \"%s\"",
1764  opcname, accessMethodName)));
1765  tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opClassId));
1766  }
1767 
1768  if (!HeapTupleIsValid(tuple))
1769  ereport(ERROR,
1770  (errcode(ERRCODE_UNDEFINED_OBJECT),
1771  errmsg("operator class \"%s\" does not exist for access method \"%s\"",
1772  NameListToString(opclass), accessMethodName)));
1773 
1774  /*
1775  * Verify that the index operator class accepts this datatype. Note we
1776  * will accept binary compatibility.
1777  */
1778  opClassId = HeapTupleGetOid(tuple);
1779  opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype;
1780 
1781  if (!IsBinaryCoercible(attrType, opInputType))
1782  ereport(ERROR,
1783  (errcode(ERRCODE_DATATYPE_MISMATCH),
1784  errmsg("operator class \"%s\" does not accept data type %s",
1785  NameListToString(opclass), format_type_be(attrType))));
1786 
1787  ReleaseSysCache(tuple);
1788 
1789  return opClassId;
1790 }
1791 
1792 /*
1793  * GetDefaultOpClass
1794  *
1795  * Given the OIDs of a datatype and an access method, find the default
1796  * operator class, if any. Returns InvalidOid if there is none.
1797  */
1798 Oid
1799 GetDefaultOpClass(Oid type_id, Oid am_id)
1800 {
1801  Oid result = InvalidOid;
1802  int nexact = 0;
1803  int ncompatible = 0;
1804  int ncompatiblepreferred = 0;
1805  Relation rel;
1806  ScanKeyData skey[1];
1807  SysScanDesc scan;
1808  HeapTuple tup;
1809  TYPCATEGORY tcategory;
1810 
1811  /* If it's a domain, look at the base type instead */
1812  type_id = getBaseType(type_id);
1813 
1814  tcategory = TypeCategory(type_id);
1815 
1816  /*
1817  * We scan through all the opclasses available for the access method,
1818  * looking for one that is marked default and matches the target type
1819  * (either exactly or binary-compatibly, but prefer an exact match).
1820  *
1821  * We could find more than one binary-compatible match. If just one is
1822  * for a preferred type, use that one; otherwise we fail, forcing the user
1823  * to specify which one he wants. (The preferred-type special case is a
1824  * kluge for varchar: it's binary-compatible to both text and bpchar, so
1825  * we need a tiebreaker.) If we find more than one exact match, then
1826  * someone put bogus entries in pg_opclass.
1827  */
1828  rel = heap_open(OperatorClassRelationId, AccessShareLock);
1829 
1830  ScanKeyInit(&skey[0],
1831  Anum_pg_opclass_opcmethod,
1832  BTEqualStrategyNumber, F_OIDEQ,
1833  ObjectIdGetDatum(am_id));
1834 
1835  scan = systable_beginscan(rel, OpclassAmNameNspIndexId, true,
1836  NULL, 1, skey);
1837 
1838  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1839  {
1840  Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
1841 
1842  /* ignore altogether if not a default opclass */
1843  if (!opclass->opcdefault)
1844  continue;
1845  if (opclass->opcintype == type_id)
1846  {
1847  nexact++;
1848  result = HeapTupleGetOid(tup);
1849  }
1850  else if (nexact == 0 &&
1851  IsBinaryCoercible(type_id, opclass->opcintype))
1852  {
1853  if (IsPreferredType(tcategory, opclass->opcintype))
1854  {
1855  ncompatiblepreferred++;
1856  result = HeapTupleGetOid(tup);
1857  }
1858  else if (ncompatiblepreferred == 0)
1859  {
1860  ncompatible++;
1861  result = HeapTupleGetOid(tup);
1862  }
1863  }
1864  }
1865 
1866  systable_endscan(scan);
1867 
1869 
1870  /* raise error if pg_opclass contains inconsistent data */
1871  if (nexact > 1)
1872  ereport(ERROR,
1874  errmsg("there are multiple default operator classes for data type %s",
1875  format_type_be(type_id))));
1876 
1877  if (nexact == 1 ||
1878  ncompatiblepreferred == 1 ||
1879  (ncompatiblepreferred == 0 && ncompatible == 1))
1880  return result;
1881 
1882  return InvalidOid;
1883 }
1884 
1885 /*
1886  * makeObjectName()
1887  *
1888  * Create a name for an implicitly created index, sequence, constraint,
1889  * extended statistics, etc.
1890  *
1891  * The parameters are typically: the original table name, the original field
1892  * name, and a "type" string (such as "seq" or "pkey"). The field name
1893  * and/or type can be NULL if not relevant.
1894  *
1895  * The result is a palloc'd string.
1896  *
1897  * The basic result we want is "name1_name2_label", omitting "_name2" or
1898  * "_label" when those parameters are NULL. However, we must generate
1899  * a name with less than NAMEDATALEN characters! So, we truncate one or
1900  * both names if necessary to make a short-enough string. The label part
1901  * is never truncated (so it had better be reasonably short).
1902  *
1903  * The caller is responsible for checking uniqueness of the generated
1904  * name and retrying as needed; retrying will be done by altering the
1905  * "label" string (which is why we never truncate that part).
1906  */
1907 char *
1908 makeObjectName(const char *name1, const char *name2, const char *label)
1909 {
1910  char *name;
1911  int overhead = 0; /* chars needed for label and underscores */
1912  int availchars; /* chars available for name(s) */
1913  int name1chars; /* chars allocated to name1 */
1914  int name2chars; /* chars allocated to name2 */
1915  int ndx;
1916 
1917  name1chars = strlen(name1);
1918  if (name2)
1919  {
1920  name2chars = strlen(name2);
1921  overhead++; /* allow for separating underscore */
1922  }
1923  else
1924  name2chars = 0;
1925  if (label)
1926  overhead += strlen(label) + 1;
1927 
1928  availchars = NAMEDATALEN - 1 - overhead;
1929  Assert(availchars > 0); /* else caller chose a bad label */
1930 
1931  /*
1932  * If we must truncate, preferentially truncate the longer name. This
1933  * logic could be expressed without a loop, but it's simple and obvious as
1934  * a loop.
1935  */
1936  while (name1chars + name2chars > availchars)
1937  {
1938  if (name1chars > name2chars)
1939  name1chars--;
1940  else
1941  name2chars--;
1942  }
1943 
1944  name1chars = pg_mbcliplen(name1, name1chars, name1chars);
1945  if (name2)
1946  name2chars = pg_mbcliplen(name2, name2chars, name2chars);
1947 
1948  /* Now construct the string using the chosen lengths */
1949  name = palloc(name1chars + name2chars + overhead + 1);
1950  memcpy(name, name1, name1chars);
1951  ndx = name1chars;
1952  if (name2)
1953  {
1954  name[ndx++] = '_';
1955  memcpy(name + ndx, name2, name2chars);
1956  ndx += name2chars;
1957  }
1958  if (label)
1959  {
1960  name[ndx++] = '_';
1961  strcpy(name + ndx, label);
1962  }
1963  else
1964  name[ndx] = '\0';
1965 
1966  return name;
1967 }
1968 
1969 /*
1970  * Select a nonconflicting name for a new relation. This is ordinarily
1971  * used to choose index names (which is why it's here) but it can also
1972  * be used for sequences, or any autogenerated relation kind.
1973  *
1974  * name1, name2, and label are used the same way as for makeObjectName(),
1975  * except that the label can't be NULL; digits will be appended to the label
1976  * if needed to create a name that is unique within the specified namespace.
1977  *
1978  * Note: it is theoretically possible to get a collision anyway, if someone
1979  * else chooses the same name concurrently. This is fairly unlikely to be
1980  * a problem in practice, especially if one is holding an exclusive lock on
1981  * the relation identified by name1. However, if choosing multiple names
1982  * within a single command, you'd better create the new object and do
1983  * CommandCounterIncrement before choosing the next one!
1984  *
1985  * Returns a palloc'd string.
1986  */
1987 char *
1988 ChooseRelationName(const char *name1, const char *name2,
1989  const char *label, Oid namespaceid)
1990 {
1991  int pass = 0;
1992  char *relname = NULL;
1993  char modlabel[NAMEDATALEN];
1994 
1995  /* try the unmodified label first */
1996  StrNCpy(modlabel, label, sizeof(modlabel));
1997 
1998  for (;;)
1999  {
2000  relname = makeObjectName(name1, name2, modlabel);
2001 
2002  if (!OidIsValid(get_relname_relid(relname, namespaceid)))
2003  break;
2004 
2005  /* found a conflict, so try a new name component */
2006  pfree(relname);
2007  snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
2008  }
2009 
2010  return relname;
2011 }
2012 
2013 /*
2014  * Select the name to be used for an index.
2015  *
2016  * The argument list is pretty ad-hoc :-(
2017  */
2018 static char *
2019 ChooseIndexName(const char *tabname, Oid namespaceId,
2020  List *colnames, List *exclusionOpNames,
2021  bool primary, bool isconstraint)
2022 {
2023  char *indexname;
2024 
2025  if (primary)
2026  {
2027  /* the primary key's name does not depend on the specific column(s) */
2028  indexname = ChooseRelationName(tabname,
2029  NULL,
2030  "pkey",
2031  namespaceId);
2032  }
2033  else if (exclusionOpNames != NIL)
2034  {
2035  indexname = ChooseRelationName(tabname,
2036  ChooseIndexNameAddition(colnames),
2037  "excl",
2038  namespaceId);
2039  }
2040  else if (isconstraint)
2041  {
2042  indexname = ChooseRelationName(tabname,
2043  ChooseIndexNameAddition(colnames),
2044  "key",
2045  namespaceId);
2046  }
2047  else
2048  {
2049  indexname = ChooseRelationName(tabname,
2050  ChooseIndexNameAddition(colnames),
2051  "idx",
2052  namespaceId);
2053  }
2054 
2055  return indexname;
2056 }
2057 
2058 /*
2059  * Generate "name2" for a new index given the list of column names for it
2060  * (as produced by ChooseIndexColumnNames). This will be passed to
2061  * ChooseRelationName along with the parent table name and a suitable label.
2062  *
2063  * We know that less than NAMEDATALEN characters will actually be used,
2064  * so we can truncate the result once we've generated that many.
2065  *
2066  * XXX See also ChooseExtendedStatisticNameAddition.
2067  */
2068 static char *
2070 {
2071  char buf[NAMEDATALEN * 2];
2072  int buflen = 0;
2073  ListCell *lc;
2074 
2075  buf[0] = '\0';
2076  foreach(lc, colnames)
2077  {
2078  const char *name = (const char *) lfirst(lc);
2079 
2080  if (buflen > 0)
2081  buf[buflen++] = '_'; /* insert _ between names */
2082 
2083  /*
2084  * At this point we have buflen <= NAMEDATALEN. name should be less
2085  * than NAMEDATALEN already, but use strlcpy for paranoia.
2086  */
2087  strlcpy(buf + buflen, name, NAMEDATALEN);
2088  buflen += strlen(buf + buflen);
2089  if (buflen >= NAMEDATALEN)
2090  break;
2091  }
2092  return pstrdup(buf);
2093 }
2094 
2095 /*
2096  * Select the actual names to be used for the columns of an index, given the
2097  * list of IndexElems for the columns. This is mostly about ensuring the
2098  * names are unique so we don't get a conflicting-attribute-names error.
2099  *
2100  * Returns a List of plain strings (char *, not String nodes).
2101  */
2102 static List *
2104 {
2105  List *result = NIL;
2106  ListCell *lc;
2107 
2108  foreach(lc, indexElems)
2109  {
2110  IndexElem *ielem = (IndexElem *) lfirst(lc);
2111  const char *origname;
2112  const char *curname;
2113  int i;
2114  char buf[NAMEDATALEN];
2115 
2116  /* Get the preliminary name from the IndexElem */
2117  if (ielem->indexcolname)
2118  origname = ielem->indexcolname; /* caller-specified name */
2119  else if (ielem->name)
2120  origname = ielem->name; /* simple column reference */
2121  else
2122  origname = "expr"; /* default name for expression */
2123 
2124  /* If it conflicts with any previous column, tweak it */
2125  curname = origname;
2126  for (i = 1;; i++)
2127  {
2128  ListCell *lc2;
2129  char nbuf[32];
2130  int nlen;
2131 
2132  foreach(lc2, result)
2133  {
2134  if (strcmp(curname, (char *) lfirst(lc2)) == 0)
2135  break;
2136  }
2137  if (lc2 == NULL)
2138  break; /* found nonconflicting name */
2139 
2140  sprintf(nbuf, "%d", i);
2141 
2142  /* Ensure generated names are shorter than NAMEDATALEN */
2143  nlen = pg_mbcliplen(origname, strlen(origname),
2144  NAMEDATALEN - 1 - strlen(nbuf));
2145  memcpy(buf, origname, nlen);
2146  strcpy(buf + nlen, nbuf);
2147  curname = buf;
2148  }
2149 
2150  /* And attach to the result list */
2151  result = lappend(result, pstrdup(curname));
2152  }
2153  return result;
2154 }
2155 
2156 /*
2157  * ReindexIndex
2158  * Recreate a specific index.
2159  */
2160 void
2161 ReindexIndex(RangeVar *indexRelation, int options)
2162 {
2163  Oid indOid;
2164  Oid heapOid = InvalidOid;
2165  Relation irel;
2166  char persistence;
2167 
2168  /*
2169  * Find and lock index, and check permissions on table; use callback to
2170  * obtain lock on table first, to avoid deadlock hazard. The lock level
2171  * used here must match the index lock obtained in reindex_index().
2172  */
2173  indOid = RangeVarGetRelidExtended(indexRelation, AccessExclusiveLock,
2174  0,
2176  (void *) &heapOid);
2177 
2178  /*
2179  * Obtain the current persistence of the existing index. We already hold
2180  * lock on the index.
2181  */
2182  irel = index_open(indOid, NoLock);
2183 
2184  if (irel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2185  {
2187  return;
2188  }
2189 
2190  persistence = irel->rd_rel->relpersistence;
2191  index_close(irel, NoLock);
2192 
2193  reindex_index(indOid, false, persistence, options);
2194 }
2195 
2196 /*
2197  * Check permissions on table before acquiring relation lock; also lock
2198  * the heap before the RangeVarGetRelidExtended takes the index lock, to avoid
2199  * deadlocks.
2200  */
2201 static void
2203  Oid relId, Oid oldRelId, void *arg)
2204 {
2205  char relkind;
2206  Oid *heapOid = (Oid *) arg;
2207 
2208  /*
2209  * If we previously locked some other index's heap, and the name we're
2210  * looking up no longer refers to that relation, release the now-useless
2211  * lock.
2212  */
2213  if (relId != oldRelId && OidIsValid(oldRelId))
2214  {
2215  /* lock level here should match reindex_index() heap lock */
2216  UnlockRelationOid(*heapOid, ShareLock);
2217  *heapOid = InvalidOid;
2218  }
2219 
2220  /* If the relation does not exist, there's nothing more to do. */
2221  if (!OidIsValid(relId))
2222  return;
2223 
2224  /*
2225  * If the relation does exist, check whether it's an index. But note that
2226  * the relation might have been dropped between the time we did the name
2227  * lookup and now. In that case, there's nothing to do.
2228  */
2229  relkind = get_rel_relkind(relId);
2230  if (!relkind)
2231  return;
2232  if (relkind != RELKIND_INDEX &&
2233  relkind != RELKIND_PARTITIONED_INDEX)
2234  ereport(ERROR,
2235  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2236  errmsg("\"%s\" is not an index", relation->relname)));
2237 
2238  /* Check permissions */
2239  if (!pg_class_ownercheck(relId, GetUserId()))
2241 
2242  /* Lock heap before index to avoid deadlock. */
2243  if (relId != oldRelId)
2244  {
2245  /*
2246  * Lock level here should match reindex_index() heap lock. If the OID
2247  * isn't valid, it means the index as concurrently dropped, which is
2248  * not a problem for us; just return normally.
2249  */
2250  *heapOid = IndexGetRelation(relId, true);
2251  if (OidIsValid(*heapOid))
2252  LockRelationOid(*heapOid, ShareLock);
2253  }
2254 }
2255 
2256 /*
2257  * ReindexTable
2258  * Recreate all indexes of a table (and of its toast table, if any)
2259  */
2260 Oid
2262 {
2263  Oid heapOid;
2264 
2265  /* The lock level used here should match reindex_relation(). */
2266  heapOid = RangeVarGetRelidExtended(relation, ShareLock, 0,
2268 
2269  if (!reindex_relation(heapOid,
2272  options))
2273  ereport(NOTICE,
2274  (errmsg("table \"%s\" has no indexes",
2275  relation->relname)));
2276 
2277  return heapOid;
2278 }
2279 
2280 /*
2281  * ReindexMultipleTables
2282  * Recreate indexes of tables selected by objectName/objectKind.
2283  *
2284  * To reduce the probability of deadlocks, each table is reindexed in a
2285  * separate transaction, so we can release the lock on it right away.
2286  * That means this must not be called within a user transaction block!
2287  */
2288 void
2289 ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
2290  int options)
2291 {
2292  Oid objectOid;
2293  Relation relationRelation;
2294  HeapScanDesc scan;
2295  ScanKeyData scan_keys[1];
2296  HeapTuple tuple;
2297  MemoryContext private_context;
2298  MemoryContext old;
2299  List *relids = NIL;
2300  ListCell *l;
2301  int num_keys;
2302 
2303  AssertArg(objectName);
2304  Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
2305  objectKind == REINDEX_OBJECT_SYSTEM ||
2306  objectKind == REINDEX_OBJECT_DATABASE);
2307 
2308  /*
2309  * Get OID of object to reindex, being the database currently being used
2310  * by session for a database or for system catalogs, or the schema defined
2311  * by caller. At the same time do permission checks that need different
2312  * processing depending on the object type.
2313  */
2314  if (objectKind == REINDEX_OBJECT_SCHEMA)
2315  {
2316  objectOid = get_namespace_oid(objectName, false);
2317 
2318  if (!pg_namespace_ownercheck(objectOid, GetUserId()))
2320  objectName);
2321  }
2322  else
2323  {
2324  objectOid = MyDatabaseId;
2325 
2326  if (strcmp(objectName, get_database_name(objectOid)) != 0)
2327  ereport(ERROR,
2328  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2329  errmsg("can only reindex the currently open database")));
2330  if (!pg_database_ownercheck(objectOid, GetUserId()))
2332  objectName);
2333  }
2334 
2335  /*
2336  * Create a memory context that will survive forced transaction commits we
2337  * do below. Since it is a child of PortalContext, it will go away
2338  * eventually even if we suffer an error; there's no need for special
2339  * abort cleanup logic.
2340  */
2341  private_context = AllocSetContextCreate(PortalContext,
2342  "ReindexMultipleTables",
2344 
2345  /*
2346  * Define the search keys to find the objects to reindex. For a schema, we
2347  * select target relations using relnamespace, something not necessary for
2348  * a database-wide operation.
2349  */
2350  if (objectKind == REINDEX_OBJECT_SCHEMA)
2351  {
2352  num_keys = 1;
2353  ScanKeyInit(&scan_keys[0],
2354  Anum_pg_class_relnamespace,
2355  BTEqualStrategyNumber, F_OIDEQ,
2356  ObjectIdGetDatum(objectOid));
2357  }
2358  else
2359  num_keys = 0;
2360 
2361  /*
2362  * Scan pg_class to build a list of the relations we need to reindex.
2363  *
2364  * We only consider plain relations and materialized views here (toast
2365  * rels will be processed indirectly by reindex_relation).
2366  */
2367  relationRelation = heap_open(RelationRelationId, AccessShareLock);
2368  scan = heap_beginscan_catalog(relationRelation, num_keys, scan_keys);
2369  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2370  {
2371  Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
2372  Oid relid = HeapTupleGetOid(tuple);
2373 
2374  /*
2375  * Only regular tables and matviews can have indexes, so ignore any
2376  * other kind of relation.
2377  *
2378  * It is tempting to also consider partitioned tables here, but that
2379  * has the problem that if the children are in the same schema, they
2380  * would be processed twice. Maybe we could have a separate list of
2381  * partitioned tables, and expand that afterwards into relids,
2382  * ignoring any duplicates.
2383  */
2384  if (classtuple->relkind != RELKIND_RELATION &&
2385  classtuple->relkind != RELKIND_MATVIEW)
2386  continue;
2387 
2388  /* Skip temp tables of other backends; we can't reindex them at all */
2389  if (classtuple->relpersistence == RELPERSISTENCE_TEMP &&
2390  !isTempNamespace(classtuple->relnamespace))
2391  continue;
2392 
2393  /* Check user/system classification, and optionally skip */
2394  if (objectKind == REINDEX_OBJECT_SYSTEM &&
2395  !IsSystemClass(relid, classtuple))
2396  continue;
2397 
2398  /* Save the list of relation OIDs in private context */
2399  old = MemoryContextSwitchTo(private_context);
2400 
2401  /*
2402  * We always want to reindex pg_class first if it's selected to be
2403  * reindexed. This ensures that if there is any corruption in
2404  * pg_class' indexes, they will be fixed before we process any other
2405  * tables. This is critical because reindexing itself will try to
2406  * update pg_class.
2407  */
2408  if (relid == RelationRelationId)
2409  relids = lcons_oid(relid, relids);
2410  else
2411  relids = lappend_oid(relids, relid);
2412 
2413  MemoryContextSwitchTo(old);
2414  }
2415  heap_endscan(scan);
2416  heap_close(relationRelation, AccessShareLock);
2417 
2418  /* Now reindex each rel in a separate transaction */
2421  foreach(l, relids)
2422  {
2423  Oid relid = lfirst_oid(l);
2424 
2426  /* functions in indexes may want a snapshot set */
2428  if (reindex_relation(relid,
2431  options))
2432 
2433  if (options & REINDEXOPT_VERBOSE)
2434  ereport(INFO,
2435  (errmsg("table \"%s.%s\" was reindexed",
2437  get_rel_name(relid))));
2440  }
2442 
2443  MemoryContextDelete(private_context);
2444 }
2445 
2446 /*
2447  * ReindexPartitionedIndex
2448  * Reindex each child of the given partitioned index.
2449  *
2450  * Not yet implemented.
2451  */
2452 static void
2454 {
2455  ereport(ERROR,
2456  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2457  errmsg("REINDEX is not yet implemented for partitioned indexes")));
2458 }
2459 
2460 /*
2461  * Insert or delete an appropriate pg_inherits tuple to make the given index
2462  * be a partition of the indicated parent index.
2463  *
2464  * This also corrects the pg_depend information for the affected index.
2465  */
2466 void
2467 IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
2468 {
2469  Relation pg_inherits;
2470  ScanKeyData key[2];
2471  SysScanDesc scan;
2472  Oid partRelid = RelationGetRelid(partitionIdx);
2473  HeapTuple tuple;
2474  bool fix_dependencies;
2475 
2476  /* Make sure this is an index */
2477  Assert(partitionIdx->rd_rel->relkind == RELKIND_INDEX ||
2478  partitionIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX);
2479 
2480  /*
2481  * Scan pg_inherits for rows linking our index to some parent.
2482  */
2483  pg_inherits = relation_open(InheritsRelationId, RowExclusiveLock);
2484  ScanKeyInit(&key[0],
2485  Anum_pg_inherits_inhrelid,
2486  BTEqualStrategyNumber, F_OIDEQ,
2487  ObjectIdGetDatum(partRelid));
2488  ScanKeyInit(&key[1],
2489  Anum_pg_inherits_inhseqno,
2490  BTEqualStrategyNumber, F_INT4EQ,
2491  Int32GetDatum(1));
2492  scan = systable_beginscan(pg_inherits, InheritsRelidSeqnoIndexId, true,
2493  NULL, 2, key);
2494  tuple = systable_getnext(scan);
2495 
2496  if (!HeapTupleIsValid(tuple))
2497  {
2498  if (parentOid == InvalidOid)
2499  {
2500  /*
2501  * No pg_inherits row, and no parent wanted: nothing to do in this
2502  * case.
2503  */
2504  fix_dependencies = false;
2505  }
2506  else
2507  {
2508  Datum values[Natts_pg_inherits];
2509  bool isnull[Natts_pg_inherits];
2510 
2511  /*
2512  * No pg_inherits row exists, and we want a parent for this index,
2513  * so insert it.
2514  */
2515  values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(partRelid);
2516  values[Anum_pg_inherits_inhparent - 1] =
2517  ObjectIdGetDatum(parentOid);
2518  values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(1);
2519  memset(isnull, false, sizeof(isnull));
2520 
2521  tuple = heap_form_tuple(RelationGetDescr(pg_inherits),
2522  values, isnull);
2523  CatalogTupleInsert(pg_inherits, tuple);
2524 
2525  fix_dependencies = true;
2526  }
2527  }
2528  else
2529  {
2530  Form_pg_inherits inhForm = (Form_pg_inherits) GETSTRUCT(tuple);
2531 
2532  if (parentOid == InvalidOid)
2533  {
2534  /*
2535  * There exists a pg_inherits row, which we want to clear; do so.
2536  */
2537  CatalogTupleDelete(pg_inherits, &tuple->t_self);
2538  fix_dependencies = true;
2539  }
2540  else
2541  {
2542  /*
2543  * A pg_inherits row exists. If it's the same we want, then we're
2544  * good; if it differs, that amounts to a corrupt catalog and
2545  * should not happen.
2546  */
2547  if (inhForm->inhparent != parentOid)
2548  {
2549  /* unexpected: we should not get called in this case */
2550  elog(ERROR, "bogus pg_inherit row: inhrelid %u inhparent %u",
2551  inhForm->inhrelid, inhForm->inhparent);
2552  }
2553 
2554  /* already in the right state */
2555  fix_dependencies = false;
2556  }
2557  }
2558 
2559  /* done with pg_inherits */
2560  systable_endscan(scan);
2561  relation_close(pg_inherits, RowExclusiveLock);
2562 
2563  if (fix_dependencies)
2564  {
2565  ObjectAddress partIdx;
2566 
2567  /*
2568  * Insert/delete pg_depend rows. If setting a parent, add an
2569  * INTERNAL_AUTO dependency to the parent index; if making standalone,
2570  * remove all existing rows and put back the regular dependency on the
2571  * table.
2572  */
2573  ObjectAddressSet(partIdx, RelationRelationId, partRelid);
2574 
2575  if (OidIsValid(parentOid))
2576  {
2577  ObjectAddress parentIdx;
2578 
2579  ObjectAddressSet(parentIdx, RelationRelationId, parentOid);
2580  recordDependencyOn(&partIdx, &parentIdx, DEPENDENCY_INTERNAL_AUTO);
2581  }
2582  else
2583  {
2584  ObjectAddress partitionTbl;
2585 
2586  ObjectAddressSet(partitionTbl, RelationRelationId,
2587  partitionIdx->rd_index->indrelid);
2588 
2589  deleteDependencyRecordsForClass(RelationRelationId, partRelid,
2590  RelationRelationId,
2592 
2593  recordDependencyOn(&partIdx, &partitionTbl, DEPENDENCY_AUTO);
2594  }
2595 
2596  /* make our updates visible */
2598  }
2599 }
bool deferrable
Definition: parsenodes.h:2734
signed short int16
Definition: c.h:312
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:722
#define NIL
Definition: pg_list.h:69
Definition: c.h:555
bool primary
Definition: parsenodes.h:2732
VirtualTransactionId * GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
Definition: procarray.c:2474
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1382
MemoryContext ii_Context
Definition: execnodes.h:171
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3592
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition: relcache.c:5001
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:126
LockRelId lockRelId
Definition: rel.h:44
void RangeVarCallbackOwnsTable(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: tablecmds.c:13374
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
bool amcanmulticol
Definition: amapi.h:180
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
static bool CheckMutability(Expr *expr)
Definition: indexcmds.c:1323
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4701
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3024
static char * ChooseIndexNameAddition(List *colnames)
Definition: indexcmds.c:2069
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:325
bool CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, Oid *collations1, Oid *collations2, Oid *opfamilies1, Oid *opfamilies2, AttrNumber *attmap, int maplen)
Definition: index.c:1820
#define DEBUG1
Definition: elog.h:25
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1298
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2872
int errhint(const char *fmt,...)
Definition: elog.c:987
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1799
Oid get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
SortByDir ordering
Definition: parsenodes.h:704
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
List * ii_Predicate
Definition: execnodes.h:156
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1572
List * options
Definition: parsenodes.h:2725
#define IndexIsValid(indexForm)
Definition: pg_index.h:85
uint32 TransactionId
Definition: c.h:474
#define INDEX_CREATE_IF_NOT_EXISTS
Definition: index.h:49
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
amgettuple_function amgettuple
Definition: amapi.h:219
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid ReindexTable(RangeVar *relation, int options)
Definition: indexcmds.c:2261
#define INDEX_CREATE_INVALID
Definition: index.h:51
int LOCKMODE
Definition: lockdefs.h:26
Oid GetUserId(void)
Definition: miscinit.c:379
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
void index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
Definition: index.c:3513
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
uint16 bits16
Definition: c.h:333
TransactionId xmin
Definition: proc.h:225
#define PointerGetDatum(X)
Definition: postgres.h:541
char * tableSpace
Definition: parsenodes.h:2721
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
ExprState * ii_PredicateState
Definition: execnodes.h:157
char * pstrdup(const char *in)
Definition: mcxt.c:1161
void CommitTransactionCommand(void)
Definition: xact.c:2744
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
Oid dbId
Definition: rel.h:39
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1754
Expr * expression_planner(Expr *expr)
Definition: planner.c:5888
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Node * whereClause
Definition: parsenodes.h:2726
Definition: lock.h:178
#define AccessShareLock
Definition: lockdefs.h:36
#define gettext_noop(x)
Definition: c.h:1036
List * list_copy(const List *oldlist)
Definition: list.c:1160
void index_check_primary_key(Relation heapRel, IndexInfo *indexInfo, bool is_alter_table)
Definition: index.c:213
Definition: nodes.h:517
Oid * ii_ExclusionProcs
Definition: execnodes.h:159
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
#define INFO
Definition: elog.h:33
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
List * list_concat(List *list1, List *list2)
Definition: list.c:321
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:397
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
char * format_operator(Oid operator_oid)
Definition: regproc.c:820
void PopActiveSnapshot(void)
Definition: snapmgr.c:812
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2788
bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
Definition: aclchk.c:4927
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
List * lcons_oid(Oid datum, List *list)
Definition: list.c:295
#define heap_close(r, l)
Definition: heapam.h:97
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:1745
static List * ChooseIndexColumnNames(List *indexElems)
Definition: indexcmds.c:2103
Form_pg_class rd_rel
Definition: rel.h:84
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isprimary, bool isreindex, bool parallel)
Definition: index.c:2229
Definition: primnodes.h:164
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
Definition: namespace.c:1779
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:745
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:304
#define OidIsValid(objectId)
Definition: c.h:605
ReindexObjectType
Definition: parsenodes.h:3274
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4689
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
#define OpclassAmNameNspIndexId
Definition: indexing.h:199
int natts
Definition: tupdesc.h:82
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:3272
Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, char *validnsps[], bool ignoreOids, bool isReset)
Definition: reloptions.c:773
Oid GetDefaultTablespace(char relpersistence)
Definition: tablespace.c:1113
char relkind
Definition: pg_class.h:51
Oid MyDatabaseTableSpace
Definition: globals.c:86
PGXACT * MyPgXact
Definition: proc.c:68
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:75
MemoryContext PortalContext
Definition: mcxt.c:53
List * indexIncludingParams
Definition: parsenodes.h:2723
#define INDEX_CONSTR_CREATE_INIT_DEFERRED
Definition: index.h:75
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4291
void ReindexIndex(RangeVar *indexRelation, int options)
Definition: indexcmds.c:2161
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:1908
#define NAMEDATALEN
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:74
char * relname
Definition: primnodes.h:69
Node * expr
Definition: parsenodes.h:700
char TYPCATEGORY
Definition: parse_coerce.h:21
RangeVar * relation
Definition: parsenodes.h:2718
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
List * ii_ExpressionsState
Definition: execnodes.h:155
Form_pg_index rd_index
Definition: rel.h:131
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
unsigned short uint16
Definition: c.h:324
void pfree(void *pointer)
Definition: mcxt.c:1031
#define PROC_IN_VACUUM
Definition: proc.h:54
#define linitial(l)
Definition: pg_list.h:111
List * make_ands_implicit(Expr *clause)
Definition: clauses.c:379
Oid * rd_indcollation
Definition: rel.h:165
SortByNulls nulls_ordering
Definition: parsenodes.h:705
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:312
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
int ii_NumIndexKeyAttrs
Definition: execnodes.h:152
Definition: rel.h:36
#define ACL_CREATE
Definition: parsenodes.h:84
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:299
amoptions_function amoptions
Definition: amapi.h:214
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
struct PartitionKeyData * rd_partkey
Definition: rel.h:99
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1134
ItemPointerData t_self
Definition: htup.h:65
bool has_superclass(Oid relationId)
Definition: pg_inherits.c:281
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:820
bool amcaninclude
Definition: amapi.h:196
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1687
Oid attcollation
Definition: pg_attribute.h:161
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2056
bool amcanunique
Definition: amapi.h:178
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:193
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
#define NoLock
Definition: lockdefs.h:34
LockInfoData rd_lockInfo
Definition: rel.h:87
static char * buf
Definition: pg_test_fsync.c:67
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:733
void IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
Definition: indexcmds.c:2467
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:563
Oid ResolveOpClass(List *opclass, Oid attrType, const char *accessMethodName, Oid accessMethodId)
Definition: indexcmds.c:1688
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
char * indexcolname
Definition: parsenodes.h:701
List * list_intersection(const List *list1, const List *list2)
Definition: list.c:800
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1292
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:441
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:227
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
bool ii_BrokenHotChain
Definition: execnodes.h:167
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3137
Oid * rd_opfamily
Definition: rel.h:154
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:1152
TransactionId xmin
Definition: snapshot.h:68
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1412
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3209
#define lnext(lc)
Definition: pg_list.h:105
bool ii_ReadyForInserts
Definition: execnodes.h:165
#define ereport(elevel, rest)
Definition: elog.h:122
Node * map_variable_attnos(Node *node, int target_varno, int sublevels_up, const AttrNumber *attno_map, int map_length, Oid to_rowtype, bool *found_whole_row)
#define AssertArg(condition)
Definition: c.h:701
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5169
bool inh
Definition: primnodes.h:70
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:905
bool IsBinaryCoercible(Oid srctype, Oid targettype)
void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, int options)
Definition: indexcmds.c:2289
List * lappend(List *list, void *datum)
Definition: list.c:128
void * ii_AmCache
Definition: execnodes.h:170
char * idxname
Definition: parsenodes.h:2717
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
void validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
Definition: index.c:3114
AttrNumber * convert_tuples_by_name_map(TupleDesc indesc, TupleDesc outdesc, const char *msg)
Definition: tupconvert.c:293
static void RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: indexcmds.c:2202
FormData_pg_index * Form_pg_index
Definition: pg_index.h:66
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
char * NameListToString(List *names)
Definition: namespace.c:3082
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:49
bool if_not_exists
Definition: parsenodes.h:2738
AclResult
Definition: acl.h:178
AttrNumber * partattrs
Definition: partcache.h:28
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:914
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
static void fix_dependencies(ArchiveHandle *AH)
int ii_NumIndexAttrs
Definition: execnodes.h:151
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
static char * label
Definition: pg_basebackup.c:84
Oid MyDatabaseId
Definition: globals.c:84
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1835
bool unique
Definition: parsenodes.h:2731
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
TupleDesc rd_att
Definition: rel.h:85
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:241
char * accessMethod
Definition: parsenodes.h:2720
#define INDEX_CREATE_IS_PRIMARY
Definition: index.h:45
void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode)
Definition: lmgr.c:837
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1323
bool allowSystemTableMods
Definition: globals.c:119
#define InvalidOid
Definition: postgres_ext.h:36
#define INDEX_CREATE_CONCURRENT
Definition: index.h:48
TYPCATEGORY TypeCategory(Oid type)
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1079
bytea * index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
Definition: reloptions.c:1478
List * opclass
Definition: parsenodes.h:703
#define NOTICE
Definition: elog.h:37
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
bool ii_Unique
Definition: execnodes.h:164
#define makeNode(_type_)
Definition: nodes.h:565
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * ii_Expressions
Definition: execnodes.h:154
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define StrNCpy(dst, src, len)
Definition: c.h:881
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:538
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4751
void StartTransactionCommand(void)
Definition: xact.c:2673
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:77
List * indexParams
Definition: parsenodes.h:2722
static void CheckPredicate(Expr *predicate)
Definition: indexcmds.c:1357
#define INDEX_MAX_KEYS
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:168
int ii_ParallelWorkers
Definition: execnodes.h:168
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:44
List * excludeOpNames
Definition: parsenodes.h:2727
static int list_length(const List *l)
Definition: pg_list.h:89
#define REINDEX_REL_CHECK_CONSTRAINTS
Definition: index.h:141
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
bool initdeferred
Definition: parsenodes.h:2735
bool amcanorder
Definition: amapi.h:172
char * name
Definition: parsenodes.h:699
char * idxcomment
Definition: parsenodes.h:2728
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1248
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1032
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4190
void reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, int options)
Definition: index.c:3617
bool ii_Concurrent
Definition: execnodes.h:166
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:176
#define DatumGetPointer(X)
Definition: postgres.h:534
void ConstraintSetParentConstraint(Oid childConstrId, Oid parentConstrId)
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:372
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
FormData_pg_class * Form_pg_class
Definition: pg_class.h:93
#define INDEX_CREATE_SKIP_BUILD
Definition: index.h:47
bool concurrent
Definition: parsenodes.h:2737
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define INDEX_CREATE_PARTITIONED
Definition: index.h:50
#define Int32GetDatum(X)
Definition: postgres.h:464
bool isconstraint
Definition: parsenodes.h:2733
Oid * ii_ExclusionOps
Definition: execnodes.h:158
FormData_pg_am * Form_pg_am
Definition: pg_am.h:46
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
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:1428
void list_free(List *list)
Definition: list.c:1133
#define ShareLock
Definition: lockdefs.h:41
int i
#define NameStr(name)
Definition: c.h:576
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:1380
void * arg
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124
List * collation
Definition: parsenodes.h:702
#define REINDEX_REL_PROCESS_TOAST
Definition: index.h:139
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:879
static char * ChooseIndexName(const char *tabname, Oid namespaceId, List *colnames, List *exclusionOpNames, bool primary, bool isconstraint)
Definition: indexcmds.c:2019
char * ChooseRelationName(const char *name1, const char *name2, const char *label, Oid namespaceid)
Definition: indexcmds.c:1988
bytea *(* amoptions_function)(Datum reloptions, bool validate)
Definition: amapi.h:103
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707
#define copyObject(obj)
Definition: nodes.h:630
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:153
uint16 * ii_ExclusionStrats
Definition: execnodes.h:160
static void ReindexPartitionedIndex(Relation parentIdx)
Definition: indexcmds.c:2453
#define INDEX_CREATE_ADD_CONSTRAINT
Definition: index.h:46
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2275
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2824
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:81
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
bool reindex_relation(Oid relid, int flags, int options)
Definition: index.c:3834
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3512
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:407
#define INDEX_CONSTR_CREATE_DEFERRABLE
Definition: index.h:74
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:150
Oid relationId
Definition: parsenodes.h:2719
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PROC_IS_AUTOVACUUM
Definition: proc.h:53
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define RelationGetPartitionDesc(relation)
Definition: rel.h:595
Oid relId
Definition: rel.h:38
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1054
Oid ii_Am
Definition: execnodes.h:169
#define RelationGetNamespace(relation)
Definition: rel.h:448