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