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/* context for ChooseIndexExpressionName_walker */
77typedef struct CIEN_context
78{
79 Relation rel; /* index's parent relation */
80 StringInfo buf; /* output string */
82
83/* non-export function prototypes */
84static bool CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts);
85static void CheckPredicate(Expr *predicate);
86static void ComputeIndexAttrs(ParseState *pstate,
87 IndexInfo *indexInfo,
93 const List *attList,
95 Oid relId,
96 const char *accessMethodName,
98 bool amcanorder,
99 bool isconstraint,
100 bool iswithoutoverlaps,
102 int ddl_sec_context,
103 int *ddl_save_nestlevel);
104static char *ChooseIndexName(const char *tabname, Oid namespaceId,
105 const List *colnames, const List *exclusionOpNames,
106 bool primary, bool isconstraint);
107static char *ChooseIndexNameAddition(const List *colnames);
108static List *ChooseIndexColumnNames(Relation rel, const List *indexElems);
110static bool ChooseIndexExpressionName_walker(Node *node,
111 CIEN_context *context);
112static void ReindexIndex(const ReindexStmt *stmt, const ReindexParams *params,
113 bool isTopLevel);
114static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
115 Oid relId, Oid oldRelId, void *arg);
116static Oid ReindexTable(const ReindexStmt *stmt, const ReindexParams *params,
117 bool isTopLevel);
118static void ReindexMultipleTables(const ReindexStmt *stmt,
119 const ReindexParams *params);
120static void reindex_error_callback(void *arg);
121static void ReindexPartitions(const ReindexStmt *stmt, Oid relid,
122 const ReindexParams *params, bool isTopLevel);
123static void ReindexMultipleInternal(const ReindexStmt *stmt, const List *relids,
124 const ReindexParams *params);
126 Oid relationOid,
127 const ReindexParams *params);
128static void update_relispartition(Oid relationId, bool newval);
129static inline void set_indexsafe_procflags(void);
130
131/*
132 * callback argument type for RangeVarCallbackForReindexIndex()
133 */
135{
136 ReindexParams params; /* options from statement */
137 Oid locked_table_oid; /* tracks previously locked table */
138};
139
140/*
141 * callback arguments for reindex_error_callback()
142 */
149
150/*
151 * CheckIndexCompatible
152 * Determine whether an existing index definition is compatible with a
153 * prospective index definition, such that the existing index storage
154 * could become the storage of the new index, avoiding a rebuild.
155 *
156 * 'oldId': the OID of the existing index
157 * 'accessMethodName': name of the AM to use.
158 * 'attributeList': a list of IndexElem specifying columns and expressions
159 * to index on.
160 * 'exclusionOpNames': list of names of exclusion-constraint operators,
161 * or NIL if not an exclusion constraint.
162 * 'isWithoutOverlaps': true iff this index has a WITHOUT OVERLAPS clause.
163 *
164 * This is tailored to the needs of ALTER TABLE ALTER TYPE, which recreates
165 * any indexes that depended on a changing column from their pg_get_indexdef
166 * or pg_get_constraintdef definitions. We omit some of the sanity checks of
167 * DefineIndex. We assume that the old and new indexes have the same number
168 * of columns and that if one has an expression column or predicate, both do.
169 * Errors arising from the attribute list still apply.
170 *
171 * Most column type changes that can skip a table rewrite do not invalidate
172 * indexes. We acknowledge this when all operator classes, collations and
173 * exclusion operators match. Though we could further permit intra-opfamily
174 * changes for btree and hash indexes, that adds subtle complexity with no
175 * concrete benefit for core types. Note, that INCLUDE columns aren't
176 * checked by this function, for them it's enough that table rewrite is
177 * skipped.
178 *
179 * When a comparison or exclusion operator has a polymorphic input type, the
180 * actual input types must also match. This defends against the possibility
181 * that operators could vary behavior in response to get_fn_expr_argtype().
182 * At present, this hazard is theoretical: check_exclusion_constraint() and
183 * all core index access methods decline to set fn_expr for such calls.
184 *
185 * We do not yet implement a test to verify compatibility of expression
186 * columns or predicates, so assume any such index is incompatible.
187 */
188bool
190 const char *accessMethodName,
191 const List *attributeList,
192 const List *exclusionOpNames,
194{
195 bool isconstraint;
196 Oid *typeIds;
202 HeapTuple tuple;
206 bool amcanorder;
207 bool amsummarizing;
209 IndexInfo *indexInfo;
211 int old_natts;
212 bool ret = true;
215 Relation irel;
216 int i;
217 Datum d;
218
219 /* Caller should already have the relation locked in some way. */
221
222 /*
223 * We can pretend isconstraint = false unconditionally. It only serves to
224 * decide the text of an error message that should never happen for us.
225 */
226 isconstraint = false;
227
231
232 /* look up the access method */
234 if (!HeapTupleIsValid(tuple))
237 errmsg("access method \"%s\" does not exist",
242 ReleaseSysCache(tuple);
243
244 amcanorder = amRoutine->amcanorder;
245 amsummarizing = amRoutine->amsummarizing;
246
247 /*
248 * Compute the operator classes, collations, and exclusion operators for
249 * the new index, so we can test whether it's compatible with the existing
250 * one. Note that ComputeIndexAttrs might fail here, but that's OK:
251 * DefineIndex would have failed later. Our attributeList contains only
252 * key attributes, thus we're filling ii_NumIndexAttrs and
253 * ii_NumIndexKeyAttrs with same value.
254 */
256 accessMethodId, NIL, NIL, false, false,
257 false, false, amsummarizing, isWithoutOverlaps);
263 ComputeIndexAttrs(NULL, indexInfo,
268 amcanorder, isconstraint, isWithoutOverlaps, InvalidOid,
269 0, NULL);
270
271 /* Get the soon-obsolete pg_index tuple. */
273 if (!HeapTupleIsValid(tuple))
274 elog(ERROR, "cache lookup failed for index %u", oldId);
276
277 /*
278 * We don't assess expressions or predicates; assume incompatibility.
279 * Also, if the index is invalid for any reason, treat it as incompatible.
280 */
283 indexForm->indisvalid))
284 {
285 ReleaseSysCache(tuple);
286 return false;
287 }
288
289 /* Any change in operator class or collation breaks compatibility. */
290 old_natts = indexForm->indnkeyatts;
292
295
298
299 ret = (memcmp(old_indclass->values, opclassIds, old_natts * sizeof(Oid)) == 0 &&
300 memcmp(old_indcollation->values, collationIds, old_natts * sizeof(Oid)) == 0);
301
302 ReleaseSysCache(tuple);
303
304 if (!ret)
305 return false;
306
307 /* For polymorphic opcintype, column type changes break compatibility. */
308 irel = index_open(oldId, AccessShareLock); /* caller probably has a lock */
309 for (i = 0; i < old_natts; i++)
310 {
312 TupleDescAttr(irel->rd_att, i)->atttypid != typeIds[i])
313 {
314 ret = false;
315 break;
316 }
317 }
318
319 /* Any change in opclass options break compatibility. */
320 if (ret)
321 {
323
324 for (i = 0; i < old_natts; i++)
326
328
330 }
331
332 /* Any change in exclusion operator selections breaks compatibility. */
333 if (ret && indexInfo->ii_ExclusionOps != NULL)
334 {
336 *old_procs;
338
340 ret = memcmp(old_operators, indexInfo->ii_ExclusionOps,
341 old_natts * sizeof(Oid)) == 0;
342
343 /* Require an exact input type match for polymorphic operators. */
344 if (ret)
345 {
346 for (i = 0; i < old_natts && ret; i++)
347 {
348 Oid left,
349 right;
350
351 op_input_types(indexInfo->ii_ExclusionOps[i], &left, &right);
352 if ((IsPolymorphicType(left) || IsPolymorphicType(right)) &&
353 TupleDescAttr(irel->rd_att, i)->atttypid != typeIds[i])
354 {
355 ret = false;
356 break;
357 }
358 }
359 }
360 }
361
362 index_close(irel, NoLock);
363 return ret;
364}
365
366/*
367 * CompareOpclassOptions
368 *
369 * Compare per-column opclass options which are represented by arrays of text[]
370 * datums. Both elements of arrays and array themselves can be NULL.
371 */
372static bool
373CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts)
374{
375 int i;
376 FmgrInfo fm;
377
378 if (!opts1 && !opts2)
379 return true;
380
382 for (i = 0; i < natts; i++)
383 {
384 Datum opt1 = opts1 ? opts1[i] : (Datum) 0;
385 Datum opt2 = opts2 ? opts2[i] : (Datum) 0;
386
387 if (opt1 == (Datum) 0)
388 {
389 if (opt2 == (Datum) 0)
390 continue;
391 else
392 return false;
393 }
394 else if (opt2 == (Datum) 0)
395 return false;
396
397 /*
398 * Compare non-NULL text[] datums. Use C collation to enforce binary
399 * equivalence of texts, because we don't know anything about the
400 * semantics of opclass options.
401 */
403 return false;
404 }
405
406 return true;
407}
408
409/*
410 * WaitForOlderSnapshots
411 *
412 * Wait for transactions that might have an older snapshot than the given xmin
413 * limit, because it might not contain tuples deleted just before it has
414 * been taken. Obtain a list of VXIDs of such transactions, and wait for them
415 * individually. This is used when building an index concurrently.
416 *
417 * We can exclude any running transactions that have xmin > the xmin given;
418 * their oldest snapshot must be newer than our xmin limit.
419 * We can also exclude any transactions that have xmin = zero, since they
420 * evidently have no live snapshot at all (and any one they might be in
421 * process of taking is certainly newer than ours). Transactions in other
422 * DBs can be ignored too, since they'll never even be able to see the
423 * index being worked on.
424 *
425 * We can also exclude autovacuum processes and processes running manual
426 * lazy VACUUMs, because they won't be fazed by missing index entries
427 * either. (Manual ANALYZEs, however, can't be excluded because they
428 * might be within transactions that are going to do arbitrary operations
429 * later.) Processes running CREATE INDEX CONCURRENTLY or REINDEX CONCURRENTLY
430 * on indexes that are neither expressional nor partial are also safe to
431 * ignore, since we know that those processes won't examine any data
432 * outside the table they're indexing.
433 *
434 * Also, GetCurrentVirtualXIDs never reports our own vxid, so we need not
435 * check for that.
436 *
437 * If a process goes idle-in-transaction with xmin zero, we do not need to
438 * wait for it anymore, per the above argument. We do not have the
439 * infrastructure right now to stop waiting if that happens, but we can at
440 * least avoid the folly of waiting when it is idle at the time we would
441 * begin to wait. We do this by repeatedly rechecking the output of
442 * GetCurrentVirtualXIDs. If, during any iteration, a particular vxid
443 * doesn't show up in the output, we know we can forget about it.
444 */
445void
447{
448 int n_old_snapshots;
449 int i;
451
456 if (progress)
458
459 for (i = 0; i < n_old_snapshots; i++)
460 {
462 continue; /* found uninteresting in previous cycle */
463
464 if (i > 0)
465 {
466 /* see if anything's changed ... */
469 int j;
470 int k;
471
473 true, false,
477 for (j = i; j < n_old_snapshots; j++)
478 {
480 continue; /* found uninteresting in previous cycle */
481 for (k = 0; k < n_newer_snapshots; k++)
482 {
484 newer_snapshots[k]))
485 break;
486 }
487 if (k >= n_newer_snapshots) /* not there anymore */
489 }
491 }
492
494 {
495 /* If requested, publish who we're going to wait for. */
496 if (progress)
497 {
499
500 if (holder)
502 holder->pid);
503 }
505 }
506
507 if (progress)
509 }
510}
511
512
513/*
514 * DefineIndex
515 * Creates a new index.
516 *
517 * This function manages the current userid according to the needs of pg_dump.
518 * Recreating old-database catalog entries in new-database is fine, regardless
519 * of which users would have permission to recreate those entries now. That's
520 * just preservation of state. Running opaque expressions, like calling a
521 * function named in a catalog entry or evaluating a pg_node_tree in a catalog
522 * entry, as anyone other than the object owner, is not fine. To adhere to
523 * those principles and to remain fail-safe, use the table owner userid for
524 * most ACL checks. Use the original userid for ACL checks reached without
525 * traversing opaque expressions. (pg_dump can predict such ACL checks from
526 * catalogs.) Overall, this is a mess. Future DDL development should
527 * consider offering one DDL command for catalog setup and a separate DDL
528 * command for steps that run opaque expressions.
529 *
530 * 'pstate': ParseState struct (used only for error reports; pass NULL if
531 * not available)
532 * 'tableId': the OID of the table relation on which the index is to be
533 * created
534 * 'stmt': IndexStmt describing the properties of the new index.
535 * 'indexRelationId': normally InvalidOid, but during bootstrap can be
536 * nonzero to specify a preselected OID for the index.
537 * 'parentIndexId': the OID of the parent index; InvalidOid if not the child
538 * of a partitioned index.
539 * 'parentConstraintId': the OID of the parent constraint; InvalidOid if not
540 * the child of a constraint (only used when recursing)
541 * 'total_parts': total number of direct and indirect partitions of relation;
542 * pass -1 if not known or rel is not partitioned.
543 * 'is_alter_table': this is due to an ALTER rather than a CREATE operation.
544 * 'check_rights': check for CREATE rights in namespace and tablespace. (This
545 * should be true except when ALTER is deleting/recreating an index.)
546 * 'check_not_in_use': check for table not already in use in current session.
547 * This should be true unless caller is holding the table open, in which
548 * case the caller had better have checked it earlier.
549 * 'skip_build': make the catalog entries but don't create the index files
550 * 'quiet': suppress the NOTICE chatter ordinarily provided for constraints.
551 *
552 * Returns the object address of the created index.
553 */
556 Oid tableId,
557 const IndexStmt *stmt,
561 int total_parts,
562 bool is_alter_table,
563 bool check_rights,
564 bool check_not_in_use,
565 bool skip_build,
566 bool quiet)
567{
568 bool concurrent;
569 char *indexRelationName;
570 char *accessMethodName;
571 Oid *typeIds;
581 Relation rel;
582 HeapTuple tuple;
585 bool amcanorder;
586 bool amissummarizing;
587 amoptions_function amoptions;
588 bool exclusion;
589 bool partitioned;
590 bool safe_index;
591 Datum reloptions;
593 IndexInfo *indexInfo;
594 uint16 flags;
599 ObjectAddress address;
600 LockRelId heaprelid;
602 LOCKMODE lockmode;
603 Snapshot snapshot;
607
609
611
612 /*
613 * Some callers need us to run with an empty default_tablespace; this is a
614 * necessary hack to be able to reproduce catalog state accurately when
615 * recreating indexes after table-rewriting ALTER TABLE.
616 */
617 if (stmt->reset_default_tblspc)
618 (void) set_config_option("default_tablespace", "",
620 GUC_ACTION_SAVE, true, 0, false);
621
622 /*
623 * Force non-concurrent build on temporary relations, even if CONCURRENTLY
624 * was requested. Other backends can't access a temporary relation, so
625 * there's no harm in grabbing a stronger lock, and a non-concurrent DROP
626 * is more efficient. Do this before any use of the concurrent option is
627 * done.
628 */
630 concurrent = true;
631 else
632 concurrent = false;
633
634 /*
635 * Start progress report. If we're building a partition, this was already
636 * done.
637 */
639 {
642 concurrent ?
645 }
646
647 /*
648 * No index OID to report yet
649 */
651 InvalidOid);
652
653 /*
654 * count key attributes in index
655 */
656 numberOfKeyAttributes = list_length(stmt->indexParams);
657
658 /*
659 * Calculate the new list of index columns including both key columns and
660 * INCLUDE columns. Later we can determine which of these are key
661 * columns, and which are just part of the INCLUDE list by checking the
662 * list position. A list item in a position less than ii_NumIndexKeyAttrs
663 * is part of the key columns, and anything equal to and over is part of
664 * the INCLUDE columns.
665 */
666 allIndexParams = list_concat_copy(stmt->indexParams,
667 stmt->indexIncludingParams);
669
670 if (numberOfKeyAttributes <= 0)
673 errmsg("must specify at least one column")));
677 errmsg("cannot use more than %d columns in an index",
679
680 /*
681 * Only SELECT ... FOR UPDATE/SHARE are allowed while doing a standard
682 * index build; but for concurrent builds we allow INSERT/UPDATE/DELETE
683 * (but not VACUUM).
684 *
685 * NB: Caller is responsible for making sure that tableId refers to the
686 * relation on which the index should be built; except in bootstrap mode,
687 * this will typically require the caller to have already locked the
688 * relation. To avoid lock upgrade hazards, that lock should be at least
689 * as strong as the one we take here.
690 *
691 * NB: If the lock strength here ever changes, code that is run by
692 * parallel workers under the control of certain particular ambuild
693 * functions will need to be updated, too.
694 */
695 lockmode = concurrent ? ShareUpdateExclusiveLock : ShareLock;
696 rel = table_open(tableId, lockmode);
697
698 /*
699 * Switch to the table owner's userid, so that any index functions are run
700 * as that user. Also lock down security-restricted operations. We
701 * already arranged to make GUC variable changes local to this command.
702 */
704 SetUserIdAndSecContext(rel->rd_rel->relowner,
706
708
709 /*
710 * It has exclusion constraint behavior if it's an EXCLUDE constraint or a
711 * temporal PRIMARY KEY/UNIQUE constraint
712 */
713 exclusion = stmt->excludeOpNames || stmt->iswithoutoverlaps;
714
715 /* Ensure that it makes sense to index this kind of relation */
716 switch (rel->rd_rel->relkind)
717 {
718 case RELKIND_RELATION:
719 case RELKIND_MATVIEW:
721 /* OK */
722 break;
723 default:
726 errmsg("cannot create index on relation \"%s\"",
729 break;
730 }
731
732 /*
733 * Establish behavior for partitioned tables, and verify sanity of
734 * parameters.
735 *
736 * We do not build an actual index in this case; we only create a few
737 * catalog entries. The actual indexes are built by recursing for each
738 * partition.
739 */
741 if (partitioned)
742 {
743 /*
744 * Note: we check 'stmt->concurrent' rather than 'concurrent', so that
745 * the error is thrown also for temporary tables. Seems better to be
746 * consistent, even though we could do it on temporary table because
747 * we're not actually doing it concurrently.
748 */
749 if (stmt->concurrent)
752 errmsg("cannot create index on partitioned table \"%s\" concurrently",
754 }
755
756 /*
757 * Don't try to CREATE INDEX on temp tables of other backends.
758 */
759 if (RELATION_IS_OTHER_TEMP(rel))
762 errmsg("cannot create indexes on temporary tables of other sessions")));
763
764 /*
765 * Unless our caller vouches for having checked this already, insist that
766 * the table not be in use by our own session, either. Otherwise we might
767 * fail to make entries in the new index (for instance, if an INSERT or
768 * UPDATE is in progress and has already made its list of target indexes).
769 */
771 CheckTableNotInUse(rel, "CREATE INDEX");
772
773 /*
774 * Verify we (still) have CREATE rights in the rel's namespace.
775 * (Presumably we did when the rel was created, but maybe not anymore.)
776 * Skip check if caller doesn't want it. Also skip check if
777 * bootstrapping, since permissions machinery may not be working yet.
778 */
780 {
782
784 ACL_CREATE);
785 if (aclresult != ACLCHECK_OK)
788 }
789
790 /*
791 * Select tablespace to use. If not specified, use default tablespace
792 * (which may in turn default to database's default).
793 */
794 if (stmt->tableSpace)
795 {
796 tablespaceId = get_tablespace_oid(stmt->tableSpace, false);
800 errmsg("cannot specify default tablespace for partitioned relations")));
801 }
802 else
803 {
804 tablespaceId = GetDefaultTablespace(rel->rd_rel->relpersistence,
806 /* note InvalidOid is OK in this case */
807 }
808
809 /* Check tablespace permissions */
810 if (check_rights &&
812 {
814
816 ACL_CREATE);
817 if (aclresult != ACLCHECK_OK)
820 }
821
822 /*
823 * Force shared indexes into the pg_global tablespace. This is a bit of a
824 * hack but seems simpler than marking them in the BKI commands. On the
825 * other hand, if it's not shared, don't allow it to be placed there.
826 */
827 if (rel->rd_rel->relisshared)
832 errmsg("only shared relations can be placed in pg_global tablespace")));
833
834 /*
835 * Choose the index column names.
836 */
838
839 /*
840 * Select name for index if caller didn't specify
841 */
842 indexRelationName = stmt->idxname;
843 if (indexRelationName == NULL)
847 stmt->excludeOpNames,
848 stmt->primary,
849 stmt->isconstraint);
850
851 /*
852 * look up the access method, verify it can handle the requested features
853 */
854 accessMethodName = stmt->accessMethod;
856 if (!HeapTupleIsValid(tuple))
857 {
858 /*
859 * Hack to provide more-or-less-transparent updating of old RTREE
860 * indexes to GiST: if RTREE is requested and not found, use GIST.
861 */
862 if (strcmp(accessMethodName, "rtree") == 0)
863 {
865 (errmsg("substituting access method \"gist\" for obsolete method \"rtree\"")));
866 accessMethodName = "gist";
868 }
869
870 if (!HeapTupleIsValid(tuple))
873 errmsg("access method \"%s\" does not exist",
875 }
879
882
883 if (stmt->unique && !stmt->iswithoutoverlaps && !amRoutine->amcanunique)
886 errmsg("access method \"%s\" does not support unique indexes",
888 if (stmt->indexIncludingParams != NIL && !amRoutine->amcaninclude)
891 errmsg("access method \"%s\" does not support included columns",
893 if (numberOfKeyAttributes > 1 && !amRoutine->amcanmulticol)
896 errmsg("access method \"%s\" does not support multicolumn indexes",
898 if (exclusion && amRoutine->amgettuple == NULL)
901 errmsg("access method \"%s\" does not support exclusion constraints",
903 if (stmt->iswithoutoverlaps && strcmp(accessMethodName, "gist") != 0)
906 errmsg("access method \"%s\" does not support WITHOUT OVERLAPS constraints",
908
909 amcanorder = amRoutine->amcanorder;
910 amoptions = amRoutine->amoptions;
911 amissummarizing = amRoutine->amsummarizing;
912
913 ReleaseSysCache(tuple);
914
915 /*
916 * Validate predicate, if given
917 */
918 if (stmt->whereClause)
919 CheckPredicate((Expr *) stmt->whereClause);
920
921 /*
922 * Parse AM-specific options, convert to text array form, validate.
923 */
924 reloptions = transformRelOptions((Datum) 0, stmt->options,
925 NULL, NULL, false, false);
926
927 (void) index_reloptions(amoptions, reloptions, true);
928
929 /*
930 * Prepare arguments for index_create, primarily an IndexInfo structure.
931 * Note that predicates must be in implicit-AND format. In a concurrent
932 * build, mark it not-ready-for-inserts.
933 */
937 NIL, /* expressions, NIL for now */
938 make_ands_implicit((Expr *) stmt->whereClause),
939 stmt->unique,
940 stmt->nulls_not_distinct,
941 !concurrent,
942 concurrent,
944 stmt->iswithoutoverlaps);
945
951 ComputeIndexAttrs(pstate,
952 indexInfo,
955 stmt->excludeOpNames, tableId,
957 amcanorder, stmt->isconstraint, stmt->iswithoutoverlaps,
960
961 /*
962 * Extra checks when creating a PRIMARY KEY index.
963 */
964 if (stmt->primary)
966
967 /*
968 * If this table is partitioned and we're creating a unique index, primary
969 * key, or exclusion constraint, make sure that the partition key is a
970 * subset of the index's columns. Otherwise it would be possible to
971 * violate uniqueness by putting values that ought to be unique in
972 * different partitions.
973 *
974 * We could lift this limitation if we had global indexes, but those have
975 * their own problems, so this is a useful feature combination.
976 */
977 if (partitioned && (stmt->unique || exclusion))
978 {
980 const char *constraint_type;
981 int i;
982
983 if (stmt->primary)
984 constraint_type = "PRIMARY KEY";
985 else if (stmt->unique)
986 constraint_type = "UNIQUE";
987 else if (stmt->excludeOpNames)
988 constraint_type = "EXCLUDE";
989 else
990 {
991 elog(ERROR, "unknown constraint type");
992 constraint_type = NULL; /* keep compiler quiet */
993 }
994
995 /*
996 * Verify that all the columns in the partition key appear in the
997 * unique key definition, with the same notion of equality.
998 */
999 for (i = 0; i < key->partnatts; i++)
1000 {
1001 bool found = false;
1002 int eq_strategy;
1004 int j;
1005
1006 /*
1007 * Identify the equality operator associated with this partkey
1008 * column. For list and range partitioning, partkeys use btree
1009 * operator classes; hash partitioning uses hash operator classes.
1010 * (Keep this in sync with ComputePartitionAttrs!)
1011 */
1012 if (key->strategy == PARTITION_STRATEGY_HASH)
1014 else
1016
1017 ptkey_eqop = get_opfamily_member(key->partopfamily[i],
1018 key->partopcintype[i],
1019 key->partopcintype[i],
1020 eq_strategy);
1021 if (!OidIsValid(ptkey_eqop))
1022 elog(ERROR, "missing operator %d(%u,%u) in partition opfamily %u",
1023 eq_strategy, key->partopcintype[i], key->partopcintype[i],
1024 key->partopfamily[i]);
1025
1026 /*
1027 * It may be possible to support UNIQUE constraints when partition
1028 * keys are expressions, but is it worth it? Give up for now.
1029 */
1030 if (key->partattrs[i] == 0)
1031 ereport(ERROR,
1033 errmsg("unsupported %s constraint with partition key definition",
1035 errdetail("%s constraints cannot be used when partition keys include expressions.",
1036 constraint_type)));
1037
1038 /* Search the index column(s) for a match */
1039 for (j = 0; j < indexInfo->ii_NumIndexKeyAttrs; j++)
1040 {
1041 if (key->partattrs[i] == indexInfo->ii_IndexAttrNumbers[j])
1042 {
1043 /*
1044 * Matched the column, now what about the collation and
1045 * equality op?
1046 */
1049
1050 if (key->partcollation[i] != collationIds[j])
1051 continue;
1052
1054 &idx_opfamily,
1055 &idx_opcintype))
1056 {
1058
1059 if (stmt->unique && !stmt->iswithoutoverlaps)
1063 COMPARE_EQ);
1064 else if (exclusion)
1065 idx_eqop = indexInfo->ii_ExclusionOps[j];
1066
1067 if (!idx_eqop)
1068 ereport(ERROR,
1070 errmsg("could not identify an equality operator for type %s", format_type_be(idx_opcintype)),
1071 errdetail("There is no suitable operator in operator family \"%s\" for access method \"%s\".",
1073
1074 if (ptkey_eqop == idx_eqop)
1075 {
1076 found = true;
1077 break;
1078 }
1079 else if (exclusion)
1080 {
1081 /*
1082 * We found a match, but it's not an equality
1083 * operator. Instead of failing below with an
1084 * error message about a missing column, fail now
1085 * and explain that the operator is wrong.
1086 */
1087 Form_pg_attribute att = TupleDescAttr(RelationGetDescr(rel), key->partattrs[i] - 1);
1088
1089 ereport(ERROR,
1091 errmsg("cannot match partition key to index on column \"%s\" using non-equal operator \"%s\"",
1092 NameStr(att->attname),
1093 get_opname(indexInfo->ii_ExclusionOps[j]))));
1094 }
1095 }
1096 }
1097 }
1098
1099 if (!found)
1100 {
1102
1104 key->partattrs[i] - 1);
1105 ereport(ERROR,
1107 /* translator: %s is UNIQUE, PRIMARY KEY, etc */
1108 errmsg("%s constraint on partitioned table must include all partitioning columns",
1110 /* translator: first %s is UNIQUE, PRIMARY KEY, etc */
1111 errdetail("%s constraint on table \"%s\" lacks column \"%s\" which is part of the partition key.",
1113 NameStr(att->attname))));
1114 }
1115 }
1116 }
1117
1118
1119 /*
1120 * We disallow indexes on system columns. They would not necessarily get
1121 * updated correctly, and they don't seem useful anyway.
1122 *
1123 * Also disallow virtual generated columns in indexes (use expression
1124 * index instead).
1125 */
1126 for (int i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1127 {
1128 AttrNumber attno = indexInfo->ii_IndexAttrNumbers[i];
1129
1130 if (attno < 0)
1131 ereport(ERROR,
1133 errmsg("index creation on system columns is not supported")));
1134
1135
1136 if (attno > 0 &&
1137 TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
1138 ereport(ERROR,
1140 stmt->primary ?
1141 errmsg("primary keys on virtual generated columns are not supported") :
1142 stmt->isconstraint ?
1143 errmsg("unique constraints on virtual generated columns are not supported") :
1144 errmsg("indexes on virtual generated columns are not supported"));
1145 }
1146
1147 /*
1148 * Also check for system and generated columns used in expressions or
1149 * predicates.
1150 */
1151 if (indexInfo->ii_Expressions || indexInfo->ii_Predicate)
1152 {
1154 int j;
1155
1156 pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs);
1157 pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs);
1158
1159 for (int i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
1160 {
1162 indexattrs))
1163 ereport(ERROR,
1165 errmsg("index creation on system columns is not supported")));
1166 }
1167
1168 /*
1169 * XXX Virtual generated columns in index expressions or predicates
1170 * could be supported, but it needs support in
1171 * RelationGetIndexExpressions() and RelationGetIndexPredicate().
1172 */
1173 j = -1;
1174 while ((j = bms_next_member(indexattrs, j)) >= 0)
1175 {
1177
1178 if (attno > 0 &&
1179 TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
1180 ereport(ERROR,
1182 stmt->isconstraint ?
1183 errmsg("unique constraints on virtual generated columns are not supported") :
1184 errmsg("indexes on virtual generated columns are not supported")));
1185 }
1186 }
1187
1188 /* Is index safe for others to ignore? See set_indexsafe_procflags() */
1189 safe_index = indexInfo->ii_Expressions == NIL &&
1190 indexInfo->ii_Predicate == NIL;
1191
1192 /*
1193 * Report index creation if appropriate (delay this till after most of the
1194 * error checks)
1195 */
1196 if (stmt->isconstraint && !quiet)
1197 {
1198 const char *constraint_type;
1199
1200 if (stmt->primary)
1201 constraint_type = "PRIMARY KEY";
1202 else if (stmt->unique)
1203 constraint_type = "UNIQUE";
1204 else if (stmt->excludeOpNames)
1205 constraint_type = "EXCLUDE";
1206 else
1207 {
1208 elog(ERROR, "unknown constraint type");
1209 constraint_type = NULL; /* keep compiler quiet */
1210 }
1211
1213 (errmsg_internal("%s %s will create implicit index \"%s\" for table \"%s\"",
1214 is_alter_table ? "ALTER TABLE / ADD" : "CREATE TABLE /",
1217 }
1218
1219 /*
1220 * A valid stmt->oldNumber implies that we already have a built form of
1221 * the index. The caller should also decline any index build.
1222 */
1223 Assert(!RelFileNumberIsValid(stmt->oldNumber) || (skip_build && !concurrent));
1224
1225 /*
1226 * Make the catalog entries for the index, including constraints. This
1227 * step also actually builds the index, except if caller requested not to
1228 * or in concurrent mode, in which case it'll be done later, or doing a
1229 * partitioned index (because those don't have storage).
1230 */
1231 flags = constr_flags = 0;
1232 if (stmt->isconstraint)
1234 if (skip_build || concurrent || partitioned)
1235 flags |= INDEX_CREATE_SKIP_BUILD;
1236 if (stmt->if_not_exists)
1238 if (concurrent)
1239 flags |= INDEX_CREATE_CONCURRENT;
1240 if (partitioned)
1241 flags |= INDEX_CREATE_PARTITIONED;
1242 if (stmt->primary)
1243 flags |= INDEX_CREATE_IS_PRIMARY;
1244
1245 /*
1246 * If the table is partitioned, and recursion was declined but partitions
1247 * exist, mark the index as invalid.
1248 */
1249 if (partitioned && stmt->relation && !stmt->relation->inh)
1250 {
1252
1253 if (pd->nparts != 0)
1254 flags |= INDEX_CREATE_INVALID;
1255 }
1256
1257 if (stmt->deferrable)
1259 if (stmt->initdeferred)
1261 if (stmt->iswithoutoverlaps)
1263
1267 stmt->oldNumber, indexInfo, indexColNames,
1270 coloptions, NULL, reloptions,
1271 flags, constr_flags,
1274
1276
1278 {
1279 /*
1280 * Roll back any GUC changes executed by index functions. Also revert
1281 * to original default_tablespace if we changed it above.
1282 */
1284
1285 /* Restore userid and security context */
1287
1288 table_close(rel, NoLock);
1289
1290 /* If this is the top-level index, we're done */
1293
1294 return address;
1295 }
1296
1297 /*
1298 * Roll back any GUC changes executed by index functions, and keep
1299 * subsequent changes local to this command. This is essential if some
1300 * index function changed a behavior-affecting GUC, e.g. search_path.
1301 */
1305
1306 /* Add any requested comment */
1307 if (stmt->idxcomment != NULL)
1309 stmt->idxcomment);
1310
1311 if (partitioned)
1312 {
1313 PartitionDesc partdesc;
1314
1315 /*
1316 * Unless caller specified to skip this step (via ONLY), process each
1317 * partition to make sure they all contain a corresponding index.
1318 *
1319 * If we're called internally (no stmt->relation), recurse always.
1320 */
1321 partdesc = RelationGetPartitionDesc(rel, true);
1322 if ((!stmt->relation || stmt->relation->inh) && partdesc->nparts > 0)
1323 {
1324 int nparts = partdesc->nparts;
1325 Oid *part_oids = palloc_array(Oid, nparts);
1326 bool invalidate_parent = false;
1329
1330 /*
1331 * Report the total number of partitions at the start of the
1332 * command; don't update it when being called recursively.
1333 */
1335 {
1336 /*
1337 * When called by ProcessUtilitySlow, the number of partitions
1338 * is passed in as an optimization; but other callers pass -1
1339 * since they don't have the value handy. This should count
1340 * partitions the same way, ie one less than the number of
1341 * relations find_all_inheritors reports.
1342 *
1343 * We assume we needn't ask find_all_inheritors to take locks,
1344 * because that should have happened already for all callers.
1345 * Even if it did not, this is safe as long as we don't try to
1346 * touch the partitions here; the worst consequence would be a
1347 * bogus progress-reporting total.
1348 */
1349 if (total_parts < 0)
1350 {
1352
1353 total_parts = list_length(children) - 1;
1354 list_free(children);
1355 }
1356
1358 total_parts);
1359 }
1360
1361 /* Make a local copy of partdesc->oids[], just for safety */
1362 memcpy(part_oids, partdesc->oids, sizeof(Oid) * nparts);
1363
1364 /*
1365 * We'll need an IndexInfo describing the parent index. The one
1366 * built above is almost good enough, but not quite, because (for
1367 * example) its predicate expression if any hasn't been through
1368 * expression preprocessing. The most reliable way to get an
1369 * IndexInfo that will match those for child indexes is to build
1370 * it the same way, using BuildIndexInfo().
1371 */
1373 indexInfo = BuildIndexInfo(parentIndex);
1374
1376
1377 /*
1378 * For each partition, scan all existing indexes; if one matches
1379 * our index definition and is not already attached to some other
1380 * parent index, attach it to the one we just created.
1381 *
1382 * If none matches, build a new index by calling ourselves
1383 * recursively with the same options (except for the index name).
1384 */
1385 for (int i = 0; i < nparts; i++)
1386 {
1392 List *childidxs;
1393 ListCell *cell;
1394 AttrMap *attmap;
1395 bool found = false;
1396
1397 childrel = table_open(childRelid, lockmode);
1398
1401 SetUserIdAndSecContext(childrel->rd_rel->relowner,
1405
1406 /*
1407 * Don't try to create indexes on foreign tables, though. Skip
1408 * those if a regular index, or fail if trying to create a
1409 * constraint index.
1410 */
1411 if (childrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1412 {
1413 if (stmt->unique || stmt->primary)
1414 ereport(ERROR,
1416 errmsg("cannot create unique index on partitioned table \"%s\"",
1418 errdetail("Table \"%s\" contains partitions that are foreign tables.",
1420
1424 table_close(childrel, lockmode);
1425 continue;
1426 }
1427
1429 attmap =
1431 parentDesc,
1432 false);
1433
1434 foreach(cell, childidxs)
1435 {
1436 Oid cldidxid = lfirst_oid(cell);
1439
1440 /* this index is already partition of another one */
1442 continue;
1443
1444 cldidx = index_open(cldidxid, lockmode);
1446 if (CompareIndexInfo(cldIdxInfo, indexInfo,
1447 cldidx->rd_indcollation,
1448 parentIndex->rd_indcollation,
1449 cldidx->rd_opfamily,
1450 parentIndex->rd_opfamily,
1451 attmap))
1452 {
1454
1455 /*
1456 * Found a match.
1457 *
1458 * If this index is being created in the parent
1459 * because of a constraint, then the child needs to
1460 * have a constraint also, so look for one. If there
1461 * is no such constraint, this index is no good, so
1462 * keep looking.
1463 */
1465 {
1466 cldConstrOid =
1468 cldidxid);
1469 if (cldConstrOid == InvalidOid)
1470 {
1471 index_close(cldidx, lockmode);
1472 continue;
1473 }
1474 }
1475
1476 /* Attach index to parent and we're done. */
1481 childRelid);
1482
1483 if (!cldidx->rd_index->indisvalid)
1484 invalidate_parent = true;
1485
1486 found = true;
1487
1488 /*
1489 * Report this partition as processed. Note that if
1490 * the partition has children itself, we'd ideally
1491 * count the children and update the progress report
1492 * for all of them; but that seems unduly expensive.
1493 * Instead, the progress report will act like all such
1494 * indirect children were processed in zero time at
1495 * the end of the command.
1496 */
1498
1499 /* keep lock till commit */
1501 break;
1502 }
1503
1504 index_close(cldidx, lockmode);
1505 }
1506
1512
1513 /*
1514 * If no matching index was found, create our own.
1515 */
1516 if (!found)
1517 {
1520
1521 /*
1522 * Build an IndexStmt describing the desired child index
1523 * in the same way that we do during ATTACH PARTITION.
1524 * Notably, we rely on generateClonedIndexStmt to produce
1525 * a search-path-independent representation, which the
1526 * original IndexStmt might not be.
1527 */
1530 attmap,
1531 NULL);
1532
1533 /*
1534 * Recurse as the starting user ID. Callee will use that
1535 * for permission checks, then switch again.
1536 */
1540 childAddr =
1541 DefineIndex(NULL, /* original pstate not applicable */
1543 InvalidOid, /* no predefined OID */
1544 indexRelationId, /* this is our child */
1546 -1,
1549 skip_build, quiet);
1552
1553 /*
1554 * Check if the index just created is valid or not, as it
1555 * could be possible that it has been switched as invalid
1556 * when recursing across multiple partition levels.
1557 */
1558 if (!get_index_isvalid(childAddr.objectId))
1559 invalidate_parent = true;
1560 }
1561
1563 }
1564
1565 index_close(parentIndex, lockmode);
1566
1567 /*
1568 * The pg_index row we inserted for this index was marked
1569 * indisvalid=true. But if we attached an existing index that is
1570 * invalid, this is incorrect, so update our row to invalid too.
1571 */
1573 {
1575 HeapTuple tup,
1576 newtup;
1577
1580 if (!HeapTupleIsValid(tup))
1581 elog(ERROR, "cache lookup failed for index %u",
1589
1590 /*
1591 * CCI here to make this update visible, in case this recurses
1592 * across multiple partition levels.
1593 */
1595 }
1596 }
1597
1598 /*
1599 * Indexes on partitioned tables are not themselves built, so we're
1600 * done here.
1601 */
1604 table_close(rel, NoLock);
1607 else
1608 {
1609 /* Update progress for an intermediate partitioned index itself */
1611 }
1612
1613 return address;
1614 }
1615
1618
1619 if (!concurrent)
1620 {
1621 /* Close the heap and we're done, in the non-concurrent case */
1622 table_close(rel, NoLock);
1623
1624 /*
1625 * If this is the top-level index, the command is done overall;
1626 * otherwise, increment progress to report one child index is done.
1627 */
1630 else
1632
1633 return address;
1634 }
1635
1636 /* save lockrelid and locktag for below, then close rel */
1637 heaprelid = rel->rd_lockInfo.lockRelId;
1638 SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
1639 table_close(rel, NoLock);
1640
1641 /*
1642 * For a concurrent build, it's important to make the catalog entries
1643 * visible to other transactions before we start to build the index. That
1644 * will prevent them from making incompatible HOT updates. The new index
1645 * will be marked not indisready and not indisvalid, so that no one else
1646 * tries to either insert into it or use it for queries.
1647 *
1648 * We must commit our current transaction so that the index becomes
1649 * visible; then start another. Note that all the data structures we just
1650 * built are lost in the commit. The only data we keep past here are the
1651 * relation IDs.
1652 *
1653 * Before committing, get a session-level lock on the table, to ensure
1654 * that neither it nor the index can be dropped before we finish. This
1655 * cannot block, even if someone else is waiting for access, because we
1656 * already have the same lock within our transaction.
1657 *
1658 * Note: we don't currently bother with a session lock on the index,
1659 * because there are no operations that could change its state while we
1660 * hold lock on the parent table. This might need to change later.
1661 */
1663
1667
1668 /* Tell concurrent index builds to ignore us, if index qualifies */
1669 if (safe_index)
1671
1672 /*
1673 * The index is now visible, so we can report the OID. While on it,
1674 * include the report for the beginning of phase 2.
1675 */
1676 {
1677 const int progress_cols[] = {
1680 };
1681 const int64 progress_vals[] = {
1684 };
1685
1687 }
1688
1689 /*
1690 * Phase 2 of concurrent index build (see comments for validate_index()
1691 * for an overview of how this works)
1692 *
1693 * Now we must wait until no running transaction could have the table open
1694 * with the old list of indexes. Use ShareLock to consider running
1695 * transactions that hold locks that permit writing to the table. Note we
1696 * do not need to worry about xacts that open the table for writing after
1697 * this point; they will see the new index when they open it.
1698 *
1699 * Note: the reason we use actual lock acquisition here, rather than just
1700 * checking the ProcArray and sleeping, is that deadlock is possible if
1701 * one of the transactions in question is blocked trying to acquire an
1702 * exclusive lock on our table. The lock code will detect deadlock and
1703 * error out properly.
1704 */
1706
1707 /*
1708 * At this moment we are sure that there are no transactions with the
1709 * table open for write that don't have this new index in their list of
1710 * indexes. We have waited out all the existing transactions and any new
1711 * transaction will have the new index in its list, but the index is still
1712 * marked as "not-ready-for-inserts". The index is consulted while
1713 * deciding HOT-safety though. This arrangement ensures that no new HOT
1714 * chains can be created where the new tuple and the old tuple in the
1715 * chain have different index keys.
1716 *
1717 * We now take a new snapshot, and build the index using all tuples that
1718 * are visible in this snapshot. We can be sure that any HOT updates to
1719 * these tuples will be compatible with the index, since any updates made
1720 * by transactions that didn't know about the index are now committed or
1721 * rolled back. Thus, each visible tuple is either the end of its
1722 * HOT-chain or the extension of the chain is HOT-safe for this index.
1723 */
1724
1725 /* Set ActiveSnapshot since functions in the indexes may need it */
1727
1728 /* Perform concurrent build of index */
1730
1731 /* we can do away with our snapshot */
1733
1734 /*
1735 * Commit this transaction to make the indisready update visible.
1736 */
1739
1740 /* Tell concurrent index builds to ignore us, if index qualifies */
1741 if (safe_index)
1743
1744 /*
1745 * Phase 3 of concurrent index build
1746 *
1747 * We once again wait until no transaction can have the table open with
1748 * the index marked as read-only for updates.
1749 */
1753
1754 /*
1755 * Now take the "reference snapshot" that will be used by validate_index()
1756 * to filter candidate tuples. Beware! There might still be snapshots in
1757 * use that treat some transaction as in-progress that our reference
1758 * snapshot treats as committed. If such a recently-committed transaction
1759 * deleted tuples in the table, we will not include them in the index; yet
1760 * those transactions which see the deleting one as still-in-progress will
1761 * expect such tuples to be there once we mark the index as valid.
1762 *
1763 * We solve this by waiting for all endangered transactions to exit before
1764 * we mark the index as valid.
1765 *
1766 * We also set ActiveSnapshot to this snap, since functions in indexes may
1767 * need a snapshot.
1768 */
1770 PushActiveSnapshot(snapshot);
1771
1772 /*
1773 * Scan the index and the heap, insert any missing index entries.
1774 */
1776
1777 /*
1778 * Drop the reference snapshot. We must do this before waiting out other
1779 * snapshot holders, else we will deadlock against other processes also
1780 * doing CREATE INDEX CONCURRENTLY, which would see our snapshot as one
1781 * they must wait for. But first, save the snapshot's xmin to use as
1782 * limitXmin for GetCurrentVirtualXIDs().
1783 */
1784 limitXmin = snapshot->xmin;
1785
1787 UnregisterSnapshot(snapshot);
1788
1789 /*
1790 * The snapshot subsystem could still contain registered snapshots that
1791 * are holding back our process's advertised xmin; in particular, if
1792 * default_transaction_isolation = serializable, there is a transaction
1793 * snapshot that is still active. The CatalogSnapshot is likewise a
1794 * hazard. To ensure no deadlocks, we must commit and start yet another
1795 * transaction, and do our wait before any snapshot has been taken in it.
1796 */
1799
1800 /* Tell concurrent index builds to ignore us, if index qualifies */
1801 if (safe_index)
1803
1804 /* We should now definitely not be advertising any xmin. */
1806
1807 /*
1808 * The index is now valid in the sense that it contains all currently
1809 * interesting tuples. But since it might not contain tuples deleted just
1810 * before the reference snap was taken, we have to wait out any
1811 * transactions that might have older snapshots.
1812 */
1813 INJECTION_POINT("define-index-before-set-valid", NULL);
1817
1818 /*
1819 * Updating pg_index might involve TOAST table access, so ensure we have a
1820 * valid snapshot.
1821 */
1823
1824 /*
1825 * Index can now be marked valid -- update its pg_index entry
1826 */
1828
1830
1831 /*
1832 * The pg_index update will cause backends (including this one) to update
1833 * relcache entries for the index itself, but we should also send a
1834 * relcache inval on the parent table to force replanning of cached plans.
1835 * Otherwise existing sessions might fail to use the new index where it
1836 * would be useful. (Note that our earlier commits did not create reasons
1837 * to replan; so relcache flush on the index itself was sufficient.)
1838 */
1840
1841 /*
1842 * Last thing to do is release the session-level lock on the parent table.
1843 */
1845
1847
1848 return address;
1849}
1850
1851
1852/*
1853 * CheckPredicate
1854 * Checks that the given partial-index predicate is valid.
1855 *
1856 * This used to also constrain the form of the predicate to forms that
1857 * indxpath.c could do something with. However, that seems overly
1858 * restrictive. One useful application of partial indexes is to apply
1859 * a UNIQUE constraint across a subset of a table, and in that scenario
1860 * any evaluable predicate will work. So accept any predicate here
1861 * (except ones requiring a plan), and let indxpath.c fend for itself.
1862 */
1863static void
1865{
1866 /*
1867 * transformExpr() should have already rejected subqueries, aggregates,
1868 * and window functions, based on the EXPR_KIND_ for a predicate.
1869 */
1870
1871 /*
1872 * A predicate using mutable functions is probably wrong, for the same
1873 * reasons that we don't allow an index expression to use one.
1874 */
1876 ereport(ERROR,
1878 errmsg("functions in index predicate must be marked IMMUTABLE")));
1879}
1880
1881/*
1882 * Compute per-index-column information, including indexed column numbers
1883 * or index expressions, opclasses and their options. Note, all output vectors
1884 * should be allocated for all columns, including "including" ones.
1885 *
1886 * If the caller switched to the table owner, ddl_userid is the role for ACL
1887 * checks reached without traversing opaque expressions. Otherwise, it's
1888 * InvalidOid, and other ddl_* arguments are undefined.
1889 */
1890static void
1892 IndexInfo *indexInfo,
1893 Oid *typeOids,
1898 const List *attList, /* list of IndexElem's */
1899 const List *exclusionOpNames,
1900 Oid relId,
1901 const char *accessMethodName,
1903 bool amcanorder,
1904 bool isconstraint,
1905 bool iswithoutoverlaps,
1907 int ddl_sec_context,
1908 int *ddl_save_nestlevel)
1909{
1911 ListCell *lc;
1912 int attn;
1913 int nkeycols = indexInfo->ii_NumIndexKeyAttrs;
1914 Oid save_userid;
1915 int save_sec_context;
1916
1917 /* Allocate space for exclusion operator info, if needed */
1918 if (exclusionOpNames)
1919 {
1925 }
1926 else
1927 nextExclOp = NULL;
1928
1929 /*
1930 * If this is a WITHOUT OVERLAPS constraint, we need space for exclusion
1931 * ops, but we don't need to parse anything, so we can let nextExclOp be
1932 * NULL. Note that for partitions/inheriting/LIKE, exclusionOpNames will
1933 * be set, so we already allocated above.
1934 */
1935 if (iswithoutoverlaps)
1936 {
1937 if (exclusionOpNames == NIL)
1938 {
1942 }
1943 nextExclOp = NULL;
1944 }
1945
1947 GetUserIdAndSecContext(&save_userid, &save_sec_context);
1948
1949 /*
1950 * process attributeList
1951 */
1952 attn = 0;
1953 foreach(lc, attList)
1954 {
1956 Oid atttype;
1957 Oid attcollation;
1958
1959 /*
1960 * Process the column-or-expression to be indexed.
1961 */
1962 if (attribute->name != NULL)
1963 {
1964 /* Simple index attribute */
1967
1968 Assert(attribute->expr == NULL);
1971 {
1972 /* difference in error message spellings is historical */
1973 if (isconstraint)
1974 ereport(ERROR,
1976 errmsg("column \"%s\" named in key does not exist",
1977 attribute->name),
1978 parser_errposition(pstate, attribute->location)));
1979 else
1980 ereport(ERROR,
1982 errmsg("column \"%s\" does not exist",
1983 attribute->name),
1984 parser_errposition(pstate, attribute->location)));
1985 }
1987 indexInfo->ii_IndexAttrNumbers[attn] = attform->attnum;
1988 atttype = attform->atttypid;
1989 attcollation = attform->attcollation;
1991 }
1992 else
1993 {
1994 /* Index expression */
1995 Node *expr = attribute->expr;
1996
1997 Assert(expr != NULL);
1998
1999 if (attn >= nkeycols)
2000 ereport(ERROR,
2002 errmsg("expressions are not supported in included columns"),
2003 parser_errposition(pstate, attribute->location)));
2004 atttype = exprType(expr);
2005 attcollation = exprCollation(expr);
2006
2007 /*
2008 * Strip any top-level COLLATE clause. This ensures that we treat
2009 * "x COLLATE y" and "(x COLLATE y)" alike.
2010 */
2011 while (IsA(expr, CollateExpr))
2012 expr = (Node *) ((CollateExpr *) expr)->arg;
2013
2014 if (IsA(expr, Var) &&
2015 ((Var *) expr)->varattno != InvalidAttrNumber)
2016 {
2017 /*
2018 * User wrote "(column)" or "(column COLLATE something)".
2019 * Treat it like simple attribute anyway.
2020 */
2021 indexInfo->ii_IndexAttrNumbers[attn] = ((Var *) expr)->varattno;
2022 }
2023 else
2024 {
2025 indexInfo->ii_IndexAttrNumbers[attn] = 0; /* marks expression */
2026 indexInfo->ii_Expressions = lappend(indexInfo->ii_Expressions,
2027 expr);
2028
2029 /*
2030 * transformExpr() should have already rejected subqueries,
2031 * aggregates, and window functions, based on the EXPR_KIND_
2032 * for an index expression.
2033 */
2034
2035 /*
2036 * An expression using mutable functions is probably wrong,
2037 * since if you aren't going to get the same result for the
2038 * same data every time, it's not clear what the index entries
2039 * mean at all.
2040 */
2042 ereport(ERROR,
2044 errmsg("functions in index expression must be marked IMMUTABLE"),
2045 parser_errposition(pstate, attribute->location)));
2046 }
2047 }
2048
2049 typeOids[attn] = atttype;
2050
2051 /*
2052 * Included columns have no collation, no opclass and no ordering
2053 * options.
2054 */
2055 if (attn >= nkeycols)
2056 {
2057 if (attribute->collation)
2058 ereport(ERROR,
2060 errmsg("including column does not support a collation"),
2061 parser_errposition(pstate, attribute->location)));
2062 if (attribute->opclass)
2063 ereport(ERROR,
2065 errmsg("including column does not support an operator class"),
2066 parser_errposition(pstate, attribute->location)));
2067 if (attribute->ordering != SORTBY_DEFAULT)
2068 ereport(ERROR,
2070 errmsg("including column does not support ASC/DESC options"),
2071 parser_errposition(pstate, attribute->location)));
2072 if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
2073 ereport(ERROR,
2075 errmsg("including column does not support NULLS FIRST/LAST options"),
2076 parser_errposition(pstate, attribute->location)));
2077
2079 opclassOptions[attn] = (Datum) 0;
2080 colOptions[attn] = 0;
2082 attn++;
2083
2084 continue;
2085 }
2086
2087 /*
2088 * Apply collation override if any. Use of ddl_userid is necessary
2089 * due to ACL checks therein, and it's safe because collations don't
2090 * contain opaque expressions (or non-opaque expressions).
2091 */
2092 if (attribute->collation)
2093 {
2095 {
2098 }
2099 attcollation = get_collation_oid(attribute->collation, false);
2101 {
2102 SetUserIdAndSecContext(save_userid, save_sec_context);
2105 }
2106 }
2107
2108 /*
2109 * Check we have a collation iff it's a collatable type. The only
2110 * expected failures here are (1) COLLATE applied to a noncollatable
2111 * type, or (2) index expression had an unresolved collation. But we
2112 * might as well code this to be a complete consistency check.
2113 */
2114 if (type_is_collatable(atttype))
2115 {
2116 if (!OidIsValid(attcollation))
2117 ereport(ERROR,
2119 errmsg("could not determine which collation to use for index expression"),
2120 errhint("Use the COLLATE clause to set the collation explicitly."),
2121 parser_errposition(pstate, attribute->location)));
2122 }
2123 else
2124 {
2125 if (OidIsValid(attcollation))
2126 ereport(ERROR,
2128 errmsg("collations are not supported by type %s",
2129 format_type_be(atttype)),
2130 parser_errposition(pstate, attribute->location)));
2131 }
2132
2133 collationOids[attn] = attcollation;
2134
2135 /*
2136 * Identify the opclass to use. Use of ddl_userid is necessary due to
2137 * ACL checks therein. This is safe despite opclasses containing
2138 * opaque expressions (specifically, functions), because only
2139 * superusers can define opclasses.
2140 */
2142 {
2145 }
2147 atttype,
2151 {
2152 SetUserIdAndSecContext(save_userid, save_sec_context);
2155 }
2156
2157 /*
2158 * Identify the exclusion operator, if any.
2159 */
2160 if (nextExclOp)
2161 {
2163 Oid opid;
2164 Oid opfamily;
2165 int strat;
2166
2167 /*
2168 * Find the operator --- it must accept the column datatype
2169 * without runtime coercion (but binary compatibility is OK).
2170 * Operators contain opaque expressions (specifically, functions).
2171 * compatible_oper_opid() boils down to oper() and
2172 * IsBinaryCoercible(). PostgreSQL would have security problems
2173 * elsewhere if oper() started calling opaque expressions.
2174 */
2176 {
2179 }
2180 opid = compatible_oper_opid(opname, atttype, atttype, false);
2182 {
2183 SetUserIdAndSecContext(save_userid, save_sec_context);
2186 }
2187
2188 /*
2189 * Only allow commutative operators to be used in exclusion
2190 * constraints. If X conflicts with Y, but Y does not conflict
2191 * with X, bad things will happen.
2192 */
2193 if (get_commutator(opid) != opid)
2194 ereport(ERROR,
2196 errmsg("operator %s is not commutative",
2197 format_operator(opid)),
2198 errdetail("Only commutative operators can be used in exclusion constraints."),
2199 parser_errposition(pstate, attribute->location)));
2200
2201 /*
2202 * Operator must be a member of the right opfamily, too
2203 */
2204 opfamily = get_opclass_family(opclassOids[attn]);
2205 strat = get_op_opfamily_strategy(opid, opfamily);
2206 if (strat == 0)
2207 ereport(ERROR,
2209 errmsg("operator %s is not a member of operator family \"%s\"",
2210 format_operator(opid),
2211 get_opfamily_name(opfamily, false)),
2212 errdetail("The exclusion operator must be related to the index operator class for the constraint."),
2213 parser_errposition(pstate, attribute->location)));
2214
2215 indexInfo->ii_ExclusionOps[attn] = opid;
2216 indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
2217 indexInfo->ii_ExclusionStrats[attn] = strat;
2219 }
2220 else if (iswithoutoverlaps)
2221 {
2222 CompareType cmptype;
2224 Oid opid;
2225
2226 if (attn == nkeycols - 1)
2227 cmptype = COMPARE_OVERLAP;
2228 else
2229 cmptype = COMPARE_EQ;
2231 indexInfo->ii_ExclusionOps[attn] = opid;
2232 indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
2233 indexInfo->ii_ExclusionStrats[attn] = strat;
2234 }
2235
2236 /*
2237 * Set up the per-column options (indoption field). For now, this is
2238 * zero for any un-ordered index, while ordered indexes have DESC and
2239 * NULLS FIRST/LAST options.
2240 */
2241 colOptions[attn] = 0;
2242 if (amcanorder)
2243 {
2244 /* default ordering is ASC */
2245 if (attribute->ordering == SORTBY_DESC)
2247 /* default null ordering is LAST for ASC, FIRST for DESC */
2248 if (attribute->nulls_ordering == SORTBY_NULLS_DEFAULT)
2249 {
2250 if (attribute->ordering == SORTBY_DESC)
2252 }
2253 else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
2255 }
2256 else
2257 {
2258 /* index AM does not support ordering */
2259 if (attribute->ordering != SORTBY_DEFAULT)
2260 ereport(ERROR,
2262 errmsg("access method \"%s\" does not support ASC/DESC options",
2264 parser_errposition(pstate, attribute->location)));
2265 if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
2266 ereport(ERROR,
2268 errmsg("access method \"%s\" does not support NULLS FIRST/LAST options",
2270 parser_errposition(pstate, attribute->location)));
2271 }
2272
2273 /* Set up the per-column opclass options (attoptions field). */
2274 if (attribute->opclassopts)
2275 {
2276 Assert(attn < nkeycols);
2277
2279 transformRelOptions((Datum) 0, attribute->opclassopts,
2280 NULL, NULL, false, false);
2281 }
2282 else
2283 opclassOptions[attn] = (Datum) 0;
2284
2285 attn++;
2286 }
2287}
2288
2289/*
2290 * Resolve possibly-defaulted operator class specification
2291 *
2292 * Note: This is used to resolve operator class specifications in index and
2293 * partition key definitions.
2294 */
2295Oid
2297 const char *accessMethodName, Oid accessMethodId)
2298{
2299 char *schemaname;
2300 char *opcname;
2301 HeapTuple tuple;
2303 Oid opClassId,
2305
2306 if (opclass == NIL)
2307 {
2308 /* no operator class specified, so find the default */
2310 if (!OidIsValid(opClassId))
2311 ereport(ERROR,
2313 errmsg("data type %s has no default operator class for access method \"%s\"",
2315 errhint("You must specify an operator class for the index or define a default operator class for the data type.")));
2316 return opClassId;
2317 }
2318
2319 /*
2320 * Specific opclass name given, so look up the opclass.
2321 */
2322
2323 /* deconstruct the name list */
2324 DeconstructQualifiedName(opclass, &schemaname, &opcname);
2325
2326 if (schemaname)
2327 {
2328 /* Look in specific schema only */
2330
2331 namespaceId = LookupExplicitNamespace(schemaname, false);
2336 }
2337 else
2338 {
2339 /* Unqualified opclass name, so search the search path */
2341 if (!OidIsValid(opClassId))
2342 ereport(ERROR,
2344 errmsg("operator class \"%s\" does not exist for access method \"%s\"",
2347 }
2348
2349 if (!HeapTupleIsValid(tuple))
2350 ereport(ERROR,
2352 errmsg("operator class \"%s\" does not exist for access method \"%s\"",
2354
2355 /*
2356 * Verify that the index operator class accepts this datatype. Note we
2357 * will accept binary compatibility.
2358 */
2359 opform = (Form_pg_opclass) GETSTRUCT(tuple);
2360 opClassId = opform->oid;
2361 opInputType = opform->opcintype;
2362
2364 ereport(ERROR,
2366 errmsg("operator class \"%s\" does not accept data type %s",
2368
2369 ReleaseSysCache(tuple);
2370
2371 return opClassId;
2372}
2373
2374/*
2375 * GetDefaultOpClass
2376 *
2377 * Given the OIDs of a datatype and an access method, find the default
2378 * operator class, if any. Returns InvalidOid if there is none.
2379 */
2380Oid
2382{
2384 int nexact = 0;
2385 int ncompatible = 0;
2386 int ncompatiblepreferred = 0;
2387 Relation rel;
2388 ScanKeyData skey[1];
2389 SysScanDesc scan;
2390 HeapTuple tup;
2392
2393 /* If it's a domain, look at the base type instead */
2394 type_id = getBaseType(type_id);
2395
2396 tcategory = TypeCategory(type_id);
2397
2398 /*
2399 * We scan through all the opclasses available for the access method,
2400 * looking for one that is marked default and matches the target type
2401 * (either exactly or binary-compatibly, but prefer an exact match).
2402 *
2403 * We could find more than one binary-compatible match. If just one is
2404 * for a preferred type, use that one; otherwise we fail, forcing the user
2405 * to specify which one he wants. (The preferred-type special case is a
2406 * kluge for varchar: it's binary-compatible to both text and bpchar, so
2407 * we need a tiebreaker.) If we find more than one exact match, then
2408 * someone put bogus entries in pg_opclass.
2409 */
2411
2412 ScanKeyInit(&skey[0],
2416
2418 NULL, 1, skey);
2419
2420 while (HeapTupleIsValid(tup = systable_getnext(scan)))
2421 {
2423
2424 /* ignore altogether if not a default opclass */
2425 if (!opclass->opcdefault)
2426 continue;
2427 if (opclass->opcintype == type_id)
2428 {
2429 nexact++;
2430 result = opclass->oid;
2431 }
2432 else if (nexact == 0 &&
2433 IsBinaryCoercible(type_id, opclass->opcintype))
2434 {
2435 if (IsPreferredType(tcategory, opclass->opcintype))
2436 {
2438 result = opclass->oid;
2439 }
2440 else if (ncompatiblepreferred == 0)
2441 {
2442 ncompatible++;
2443 result = opclass->oid;
2444 }
2445 }
2446 }
2447
2448 systable_endscan(scan);
2449
2451
2452 /* raise error if pg_opclass contains inconsistent data */
2453 if (nexact > 1)
2454 ereport(ERROR,
2456 errmsg("there are multiple default operator classes for data type %s",
2457 format_type_be(type_id))));
2458
2459 if (nexact == 1 ||
2460 ncompatiblepreferred == 1 ||
2461 (ncompatiblepreferred == 0 && ncompatible == 1))
2462 return result;
2463
2464 return InvalidOid;
2465}
2466
2467/*
2468 * GetOperatorFromCompareType
2469 *
2470 * opclass - the opclass to use
2471 * rhstype - the type for the right-hand side, or InvalidOid to use the type of the given opclass.
2472 * cmptype - kind of operator to find
2473 * opid - holds the operator we found
2474 * strat - holds the output strategy number
2475 *
2476 * Finds an operator from a CompareType. This is used for temporal index
2477 * constraints (and other temporal features) to look up equality and overlaps
2478 * operators. We ask an opclass support function to translate from the
2479 * compare type to the internal strategy numbers. Raises ERROR on search
2480 * failure.
2481 */
2482void
2484 Oid *opid, StrategyNumber *strat)
2485{
2486 Oid amid;
2487 Oid opfamily;
2488 Oid opcintype;
2489
2490 Assert(cmptype == COMPARE_EQ || cmptype == COMPARE_OVERLAP || cmptype == COMPARE_CONTAINED_BY);
2491
2492 /*
2493 * Use the opclass to get the opfamily, opcintype, and access method. If
2494 * any of this fails, quit early.
2495 */
2496 if (!get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
2497 elog(ERROR, "cache lookup failed for opclass %u", opclass);
2498
2499 amid = get_opclass_method(opclass);
2500
2501 /*
2502 * Ask the index AM to translate to its internal stratnum
2503 */
2504 *strat = IndexAmTranslateCompareType(cmptype, amid, opfamily, true);
2505 if (*strat == InvalidStrategy)
2506 ereport(ERROR,
2508 cmptype == COMPARE_EQ ? errmsg("could not identify an equality operator for type %s", format_type_be(opcintype)) :
2509 cmptype == COMPARE_OVERLAP ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) :
2510 cmptype == COMPARE_CONTAINED_BY ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0,
2511 errdetail("Could not translate compare type %d for operator family \"%s\" of access method \"%s\".",
2512 cmptype, get_opfamily_name(opfamily, false), get_am_name(amid)));
2513
2514 /*
2515 * We parameterize rhstype so foreign keys can ask for a <@ operator whose
2516 * rhs matches the aggregate function. For example range_agg returns
2517 * anymultirange.
2518 */
2519 if (!OidIsValid(rhstype))
2520 rhstype = opcintype;
2521 *opid = get_opfamily_member(opfamily, opcintype, rhstype, *strat);
2522
2523 if (!OidIsValid(*opid))
2524 ereport(ERROR,
2526 cmptype == COMPARE_EQ ? errmsg("could not identify an equality operator for type %s", format_type_be(opcintype)) :
2527 cmptype == COMPARE_OVERLAP ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) :
2528 cmptype == COMPARE_CONTAINED_BY ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0,
2529 errdetail("There is no suitable operator in operator family \"%s\" for access method \"%s\".",
2530 get_opfamily_name(opfamily, false), get_am_name(amid)));
2531}
2532
2533/*
2534 * makeObjectName()
2535 *
2536 * Create a name for an implicitly created index, sequence, constraint,
2537 * extended statistics, etc.
2538 *
2539 * The parameters are typically: the original table name, the original field
2540 * name, and a "type" string (such as "seq" or "pkey"). The field name
2541 * and/or type can be NULL if not relevant.
2542 *
2543 * The result is a palloc'd string.
2544 *
2545 * The basic result we want is "name1_name2_label", omitting "_name2" or
2546 * "_label" when those parameters are NULL. However, we must generate
2547 * a name with less than NAMEDATALEN characters! So, we truncate one or
2548 * both names if necessary to make a short-enough string. The label part
2549 * is never truncated (so it had better be reasonably short).
2550 *
2551 * The caller is responsible for checking uniqueness of the generated
2552 * name and retrying as needed; retrying will be done by altering the
2553 * "label" string (which is why we never truncate that part).
2554 */
2555char *
2556makeObjectName(const char *name1, const char *name2, const char *label)
2557{
2558 char *name;
2559 int overhead = 0; /* chars needed for label and underscores */
2560 int availchars; /* chars available for name(s) */
2561 int name1chars; /* chars allocated to name1 */
2562 int name2chars; /* chars allocated to name2 */
2563 int ndx;
2564
2566 if (name2)
2567 {
2569 overhead++; /* allow for separating underscore */
2570 }
2571 else
2572 name2chars = 0;
2573 if (label)
2574 overhead += strlen(label) + 1;
2575
2577 Assert(availchars > 0); /* else caller chose a bad label */
2578
2579 /*
2580 * If we must truncate, preferentially truncate the longer name. This
2581 * logic could be expressed without a loop, but it's simple and obvious as
2582 * a loop.
2583 */
2584 while (name1chars + name2chars > availchars)
2585 {
2586 if (name1chars > name2chars)
2587 name1chars--;
2588 else
2589 name2chars--;
2590 }
2591
2593 if (name2)
2595
2596 /* Now construct the string using the chosen lengths */
2599 ndx = name1chars;
2600 if (name2)
2601 {
2602 name[ndx++] = '_';
2604 ndx += name2chars;
2605 }
2606 if (label)
2607 {
2608 name[ndx++] = '_';
2609 strcpy(name + ndx, label);
2610 }
2611 else
2612 name[ndx] = '\0';
2613
2614 return name;
2615}
2616
2617/*
2618 * Select a nonconflicting name for a new relation. This is ordinarily
2619 * used to choose index names (which is why it's here) but it can also
2620 * be used for sequences, or any autogenerated relation kind.
2621 *
2622 * name1, name2, and label are used the same way as for makeObjectName(),
2623 * except that the label can't be NULL; digits will be appended to the label
2624 * if needed to create a name that is unique within the specified namespace.
2625 *
2626 * If isconstraint is true, we also avoid choosing a name matching any
2627 * existing constraint in the same namespace. (This is stricter than what
2628 * Postgres itself requires, but the SQL standard says that constraint names
2629 * should be unique within schemas, so we follow that for autogenerated
2630 * constraint names.)
2631 *
2632 * Note: it is theoretically possible to get a collision anyway, if someone
2633 * else chooses the same name concurrently. We shorten the race condition
2634 * window by checking for conflicting relations using SnapshotDirty, but
2635 * that doesn't close the window entirely. This is fairly unlikely to be
2636 * a problem in practice, especially if one is holding an exclusive lock on
2637 * the relation identified by name1. However, if choosing multiple names
2638 * within a single command, you'd better create the new object and do
2639 * CommandCounterIncrement before choosing the next one!
2640 *
2641 * Returns a palloc'd string.
2642 */
2643char *
2644ChooseRelationName(const char *name1, const char *name2,
2645 const char *label, Oid namespaceid,
2646 bool isconstraint)
2647{
2648 int pass = 0;
2649 char *relname = NULL;
2650 char modlabel[NAMEDATALEN];
2653
2654 /* prepare to search pg_class with a dirty snapshot */
2657
2658 /* try the unmodified label first */
2659 strlcpy(modlabel, label, sizeof(modlabel));
2660
2661 for (;;)
2662 {
2663 ScanKeyData key[2];
2664 SysScanDesc scan;
2665 bool collides;
2666
2668
2669 /* is there any conflicting relation name? */
2670 ScanKeyInit(&key[0],
2674 ScanKeyInit(&key[1],
2678
2680 true /* indexOK */ ,
2682 2, key);
2683
2685
2686 systable_endscan(scan);
2687
2688 /* break out of loop if no conflict */
2689 if (!collides)
2690 {
2691 if (!isconstraint ||
2693 break;
2694 }
2695
2696 /* found a conflict, so try a new name component */
2697 pfree(relname);
2698 snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
2699 }
2700
2702
2703 return relname;
2704}
2705
2706/*
2707 * Select the name to be used for an index.
2708 *
2709 * The argument list is pretty ad-hoc :-(
2710 */
2711static char *
2712ChooseIndexName(const char *tabname, Oid namespaceId,
2713 const List *colnames, const List *exclusionOpNames,
2714 bool primary, bool isconstraint)
2715{
2716 char *indexname;
2717
2718 if (primary)
2719 {
2720 /* the primary key's name does not depend on the specific column(s) */
2721 indexname = ChooseRelationName(tabname,
2722 NULL,
2723 "pkey",
2725 true);
2726 }
2727 else if (exclusionOpNames != NIL)
2728 {
2729 indexname = ChooseRelationName(tabname,
2730 ChooseIndexNameAddition(colnames),
2731 "excl",
2733 true);
2734 }
2735 else if (isconstraint)
2736 {
2737 indexname = ChooseRelationName(tabname,
2738 ChooseIndexNameAddition(colnames),
2739 "key",
2741 true);
2742 }
2743 else
2744 {
2745 indexname = ChooseRelationName(tabname,
2746 ChooseIndexNameAddition(colnames),
2747 "idx",
2749 false);
2750 }
2751
2752 return indexname;
2753}
2754
2755/*
2756 * Generate "name2" for a new index given the list of column names for it
2757 * (as produced by ChooseIndexColumnNames). This will be passed to
2758 * ChooseRelationName along with the parent table name and a suitable label.
2759 *
2760 * We know that less than NAMEDATALEN characters will actually be used,
2761 * so we can truncate the result once we've generated that many.
2762 *
2763 * XXX See also ChooseForeignKeyConstraintNameAddition and
2764 * ChooseExtendedStatisticNameAddition.
2765 */
2766static char *
2768{
2769 char buf[NAMEDATALEN * 2];
2770 int buflen = 0;
2771 ListCell *lc;
2772
2773 buf[0] = '\0';
2774 foreach(lc, colnames)
2775 {
2776 const char *name = (const char *) lfirst(lc);
2777
2778 if (buflen > 0)
2779 buf[buflen++] = '_'; /* insert _ between names */
2780
2781 /*
2782 * At this point we have buflen <= NAMEDATALEN. name should be less
2783 * than NAMEDATALEN already, but use strlcpy for paranoia.
2784 */
2785 strlcpy(buf + buflen, name, NAMEDATALEN);
2786 buflen += strlen(buf + buflen);
2787 if (buflen >= NAMEDATALEN)
2788 break;
2789 }
2790 return pstrdup(buf);
2791}
2792
2793/*
2794 * Select the actual names to be used for the columns of an index, given the
2795 * parent Relation and the list of IndexElems for the columns. The logic in
2796 * this function is mostly about ensuring the names are unique so we don't
2797 * get a conflicting-attribute-names error.
2798 *
2799 * Returns a List of plain strings (char *, not String nodes).
2800 */
2801static List *
2802ChooseIndexColumnNames(Relation rel, const List *indexElems)
2803{
2804 List *result = NIL;
2805 ListCell *lc;
2806
2807 foreach(lc, indexElems)
2808 {
2810 const char *origname;
2811 const char *curname;
2812 int i;
2813 char buf[NAMEDATALEN];
2814
2815 /* Get the preliminary name from the IndexElem */
2816 if (ielem->indexcolname)
2817 origname = ielem->indexcolname; /* caller-specified name */
2818 else if (ielem->name)
2819 origname = ielem->name; /* simple column reference */
2820 else
2822
2823 /* If it conflicts with any previous column, tweak it */
2824 curname = origname;
2825 for (i = 1;; i++)
2826 {
2827 ListCell *lc2;
2828 char nbuf[32];
2829 int nlen;
2830
2831 foreach(lc2, result)
2832 {
2833 if (strcmp(curname, (char *) lfirst(lc2)) == 0)
2834 break;
2835 }
2836 if (lc2 == NULL)
2837 break; /* found nonconflicting name */
2838
2839 sprintf(nbuf, "%d", i);
2840
2841 /* Ensure generated names are shorter than NAMEDATALEN */
2843 NAMEDATALEN - 1 - strlen(nbuf));
2845 strcpy(buf + nlen, nbuf);
2846 curname = buf;
2847 }
2848
2849 /* And attach to the result list */
2851 }
2852 return result;
2853}
2854
2855/*
2856 * Generate a suitable index-column name for an index expression.
2857 *
2858 * Our strategy is to collect the Var names, Const values, and function names
2859 * appearing in the expression, and print them separated by underscores.
2860 * We could expend a lot more effort to handle additional expression node
2861 * types, but this seems sufficient to usually produce a column name distinct
2862 * from other index expressions.
2863 */
2864static char *
2866{
2868 CIEN_context context;
2869 int nlen;
2870
2871 /* Prepare ... */
2873 context.rel = rel;
2874 context.buf = &buf;
2875 /* Walk the tree, stopping when we have enough text */
2877 /* Ensure generated names are shorter than NAMEDATALEN */
2878 nlen = pg_mbcliplen(buf.data, buf.len, NAMEDATALEN - 1);
2879 buf.data[nlen] = '\0';
2880 return buf.data;
2881}
2882
2883/* Recursive guts of ChooseIndexExpressionName */
2884static bool
2886 CIEN_context *context)
2887{
2888 if (node == NULL)
2889 return false;
2890 if (IsA(node, Var))
2891 {
2892 Var *var = (Var *) node;
2893 TupleDesc tupdesc = RelationGetDescr(context->rel);
2895
2896 /* Paranoia: ignore the Var if it looks fishy */
2897 if (var->varno != 1 || var->varlevelsup != 0 ||
2898 var->varattno <= 0 || var->varattno > tupdesc->natts)
2899 return false;
2900 att = TupleDescAttr(tupdesc, var->varattno - 1);
2901 if (att->attisdropped)
2902 return false; /* even more paranoia; shouldn't happen */
2903
2904 if (context->buf->len > 0)
2905 appendStringInfoChar(context->buf, '_');
2906 appendStringInfoString(context->buf, NameStr(att->attname));
2907
2908 /* Done if we've already reached NAMEDATALEN */
2909 return (context->buf->len >= NAMEDATALEN);
2910 }
2911 else if (IsA(node, Const))
2912 {
2913 Const *constval = (Const *) node;
2914
2915 if (context->buf->len > 0)
2916 appendStringInfoChar(context->buf, '_');
2917 if (constval->constisnull)
2918 appendStringInfoString(context->buf, "NULL");
2919 else
2920 {
2921 Oid typoutput;
2922 bool typIsVarlena;
2923 char *extval;
2924
2925 getTypeOutputInfo(constval->consttype,
2926 &typoutput, &typIsVarlena);
2927 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
2928
2929 /*
2930 * We sanitize constant values by dropping non-alphanumeric ASCII
2931 * characters. This is probably not really necessary, but it
2932 * reduces the odds of needing to double-quote the generated name.
2933 */
2934 for (const char *ptr = extval; *ptr; ptr++)
2935 {
2936 if (IS_HIGHBIT_SET(*ptr) ||
2937 strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2938 "abcdefghijklmnopqrstuvwxyz"
2939 "0123456789", *ptr) != NULL)
2940 appendStringInfoChar(context->buf, *ptr);
2941 }
2942 }
2943
2944 /* Done if we've already reached NAMEDATALEN */
2945 return (context->buf->len >= NAMEDATALEN);
2946 }
2947 else if (IsA(node, FuncExpr))
2948 {
2949 FuncExpr *funcexpr = (FuncExpr *) node;
2950 char *fname = get_func_name(funcexpr->funcid);
2951
2952 if (fname)
2953 {
2954 if (context->buf->len > 0)
2955 appendStringInfoChar(context->buf, '_');
2956 appendStringInfoString(context->buf, fname);
2957 }
2958 /* fall through to examine arguments */
2959 }
2960
2961 /* Abandon recursion once we reach NAMEDATALEN */
2962 if (context->buf->len >= NAMEDATALEN)
2963 return true;
2964
2966 context);
2967}
2968
2969/*
2970 * ExecReindex
2971 *
2972 * Primary entry point for manual REINDEX commands. This is mainly a
2973 * preparation wrapper for the real operations that will happen in
2974 * each subroutine of REINDEX.
2975 */
2976void
2978{
2979 ReindexParams params = {0};
2980 ListCell *lc;
2981 bool concurrently = false;
2982 bool verbose = false;
2983 char *tablespacename = NULL;
2984
2985 /* Parse option list */
2986 foreach(lc, stmt->params)
2987 {
2988 DefElem *opt = (DefElem *) lfirst(lc);
2989
2990 if (strcmp(opt->defname, "verbose") == 0)
2991 verbose = defGetBoolean(opt);
2992 else if (strcmp(opt->defname, "concurrently") == 0)
2994 else if (strcmp(opt->defname, "tablespace") == 0)
2995 tablespacename = defGetString(opt);
2996 else
2997 ereport(ERROR,
2999 errmsg("unrecognized %s option \"%s\"",
3000 "REINDEX", opt->defname),
3001 parser_errposition(pstate, opt->location)));
3002 }
3003
3004 if (concurrently)
3006 "REINDEX CONCURRENTLY");
3007
3008 params.options =
3009 (verbose ? REINDEXOPT_VERBOSE : 0) |
3011
3012 /*
3013 * Assign the tablespace OID to move indexes to, with InvalidOid to do
3014 * nothing.
3015 */
3016 if (tablespacename != NULL)
3017 {
3018 params.tablespaceOid = get_tablespace_oid(tablespacename, false);
3019
3020 /* Check permissions except when moving to database's default */
3021 if (OidIsValid(params.tablespaceOid) &&
3023 {
3025
3028 if (aclresult != ACLCHECK_OK)
3031 }
3032 }
3033 else
3034 params.tablespaceOid = InvalidOid;
3035
3036 switch (stmt->kind)
3037 {
3039 ReindexIndex(stmt, &params, isTopLevel);
3040 break;
3042 ReindexTable(stmt, &params, isTopLevel);
3043 break;
3047
3048 /*
3049 * This cannot run inside a user transaction block; if we were
3050 * inside a transaction, then its commit- and
3051 * start-transaction-command calls would not have the intended
3052 * effect!
3053 */
3055 (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" :
3056 (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" :
3057 "REINDEX DATABASE");
3058 ReindexMultipleTables(stmt, &params);
3059 break;
3060 default:
3061 elog(ERROR, "unrecognized object type: %d",
3062 (int) stmt->kind);
3063 break;
3064 }
3065}
3066
3067/*
3068 * ReindexIndex
3069 * Recreate a specific index.
3070 */
3071static void
3073{
3074 const RangeVar *indexRelation = stmt->relation;
3076 Oid indOid;
3077 char persistence;
3078 char relkind;
3079
3080 /*
3081 * Find and lock index, and check permissions on table; use callback to
3082 * obtain lock on table first, to avoid deadlock hazard. The lock level
3083 * used here must match the index lock obtained in reindex_index().
3084 *
3085 * If it's a temporary index, we will perform a non-concurrent reindex,
3086 * even if CONCURRENTLY was requested. In that case, reindex_index() will
3087 * upgrade the lock, but that's OK, because other sessions can't hold
3088 * locks on our temporary table.
3089 */
3090 state.params = *params;
3091 state.locked_table_oid = InvalidOid;
3092 indOid = RangeVarGetRelidExtended(indexRelation,
3095 0,
3097 &state);
3098
3099 /*
3100 * Obtain the current persistence and kind of the existing index. We
3101 * already hold a lock on the index.
3102 */
3103 persistence = get_rel_persistence(indOid);
3104 relkind = get_rel_relkind(indOid);
3105
3106 if (relkind == RELKIND_PARTITIONED_INDEX)
3108 else if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
3109 persistence != RELPERSISTENCE_TEMP)
3111 else
3112 {
3114
3116 reindex_index(stmt, indOid, false, persistence, &newparams);
3117 }
3118}
3119
3120/*
3121 * Check permissions on table before acquiring relation lock; also lock
3122 * the heap before the RangeVarGetRelidExtended takes the index lock, to avoid
3123 * deadlocks.
3124 */
3125static void
3127 Oid relId, Oid oldRelId, void *arg)
3128{
3129 char relkind;
3132 Oid table_oid;
3134
3135 /*
3136 * Lock level here should match table lock in reindex_index() for
3137 * non-concurrent case and table locks used by index_concurrently_*() for
3138 * concurrent case.
3139 */
3140 table_lockmode = (state->params.options & REINDEXOPT_CONCURRENTLY) != 0 ?
3142
3143 /*
3144 * If we previously locked some other index's heap, and the name we're
3145 * looking up no longer refers to that relation, release the now-useless
3146 * lock.
3147 */
3148 if (relId != oldRelId && OidIsValid(oldRelId))
3149 {
3150 UnlockRelationOid(state->locked_table_oid, table_lockmode);
3151 state->locked_table_oid = InvalidOid;
3152 }
3153
3154 /* If the relation does not exist, there's nothing more to do. */
3155 if (!OidIsValid(relId))
3156 return;
3157
3158 /* If the relation does exist, check whether it's an index. */
3159 relkind = get_rel_relkind(relId);
3160 if (relkind != RELKIND_INDEX &&
3161 relkind != RELKIND_PARTITIONED_INDEX)
3162 ereport(ERROR,
3164 errmsg("\"%s\" is not an index", relation->relname)));
3165
3166 /* Look up the index's table. */
3167 table_oid = IndexGetRelation(relId, false);
3168
3169 /*
3170 * In the unlikely event that, upon retry, we get the same index OID with
3171 * a different table OID, fail. RangeVarGetRelidExtended() will have
3172 * already locked the index in this case, and it won't retry again, so we
3173 * can't lock the newly discovered table OID without risking deadlock.
3174 * Also, while this corner case is indeed possible, it is extremely
3175 * unlikely to happen in practice, so it's probably not worth any more
3176 * effort than this.
3177 */
3178 if (relId == oldRelId && table_oid != state->locked_table_oid)
3179 ereport(ERROR,
3181 errmsg("index \"%s\" was concurrently dropped",
3182 relation->relname)));
3183
3184 /* Check permissions. */
3186 if (aclresult != ACLCHECK_OK)
3188
3189 /* Lock heap before index to avoid deadlock. */
3190 if (relId != oldRelId)
3191 {
3193 state->locked_table_oid = table_oid;
3194 }
3195}
3196
3197/*
3198 * ReindexTable
3199 * Recreate all indexes of a table (and of its toast table, if any)
3200 */
3201static Oid
3203{
3204 Oid heapOid;
3205 bool result;
3206 const RangeVar *relation = stmt->relation;
3207
3208 /*
3209 * The lock level used here should match reindex_relation().
3210 *
3211 * If it's a temporary table, we will perform a non-concurrent reindex,
3212 * even if CONCURRENTLY was requested. In that case, reindex_relation()
3213 * will upgrade the lock, but that's OK, because other sessions can't hold
3214 * locks on our temporary table.
3215 */
3216 heapOid = RangeVarGetRelidExtended(relation,
3219 0,
3221
3224 else if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
3226 {
3228
3229 if (!result)
3231 (errmsg("table \"%s\" has no indexes that can be reindexed concurrently",
3232 relation->relname)));
3233 }
3234 else
3235 {
3237
3239 result = reindex_relation(stmt, heapOid,
3242 &newparams);
3243 if (!result)
3245 (errmsg("table \"%s\" has no indexes to reindex",
3246 relation->relname)));
3247 }
3248
3249 return heapOid;
3250}
3251
3252/*
3253 * ReindexMultipleTables
3254 * Recreate indexes of tables selected by objectName/objectKind.
3255 *
3256 * To reduce the probability of deadlocks, each table is reindexed in a
3257 * separate transaction, so we can release the lock on it right away.
3258 * That means this must not be called within a user transaction block!
3259 */
3260static void
3262{
3263
3264 Oid objectOid;
3266 TableScanDesc scan;
3268 HeapTuple tuple;
3271 List *relids = NIL;
3272 int num_keys;
3273 bool concurrent_warning = false;
3274 bool tablespace_warning = false;
3275 const char *objectName = stmt->name;
3276 const ReindexObjectType objectKind = stmt->kind;
3277
3281
3282 /*
3283 * This matches the options enforced by the grammar, where the object name
3284 * is optional for DATABASE and SYSTEM.
3285 */
3287
3290 ereport(ERROR,
3292 errmsg("cannot reindex system catalogs concurrently")));
3293
3294 /*
3295 * Get OID of object to reindex, being the database currently being used
3296 * by session for a database or for system catalogs, or the schema defined
3297 * by caller. At the same time do permission checks that need different
3298 * processing depending on the object type.
3299 */
3301 {
3303
3307 objectName);
3308 }
3309 else
3310 {
3312
3314 ereport(ERROR,
3316 errmsg("can only reindex the currently open database")));
3321 }
3322
3323 /*
3324 * Create a memory context that will survive forced transaction commits we
3325 * do below. Since it is a child of PortalContext, it will go away
3326 * eventually even if we suffer an error; there's no need for special
3327 * abort cleanup logic.
3328 */
3330 "ReindexMultipleTables",
3332
3333 /*
3334 * Define the search keys to find the objects to reindex. For a schema, we
3335 * select target relations using relnamespace, something not necessary for
3336 * a database-wide operation.
3337 */
3339 {
3340 num_keys = 1;
3345 }
3346 else
3347 num_keys = 0;
3348
3349 /*
3350 * Scan pg_class to build a list of the relations we need to reindex.
3351 *
3352 * We only consider plain relations and materialized views here (toast
3353 * rels will be processed indirectly by reindex_relation).
3354 */
3357 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
3358 {
3360 Oid relid = classtuple->oid;
3361
3362 /*
3363 * Only regular tables and matviews can have indexes, so ignore any
3364 * other kind of relation.
3365 *
3366 * Partitioned tables/indexes are skipped but matching leaf partitions
3367 * are processed.
3368 */
3369 if (classtuple->relkind != RELKIND_RELATION &&
3370 classtuple->relkind != RELKIND_MATVIEW)
3371 continue;
3372
3373 /* Skip temp tables of other backends; we can't reindex them at all */
3374 if (classtuple->relpersistence == RELPERSISTENCE_TEMP &&
3375 !isTempNamespace(classtuple->relnamespace))
3376 continue;
3377
3378 /*
3379 * Check user/system classification. SYSTEM processes all the
3380 * catalogs, and DATABASE processes everything that's not a catalog.
3381 */
3383 !IsCatalogRelationOid(relid))
3384 continue;
3385 else if (objectKind == REINDEX_OBJECT_DATABASE &&
3386 IsCatalogRelationOid(relid))
3387 continue;
3388
3389 /*
3390 * We already checked privileges on the database or schema, but we
3391 * further restrict reindexing shared catalogs to roles with the
3392 * MAINTAIN privilege on the relation.
3393 */
3394 if (classtuple->relisshared &&
3396 continue;
3397
3398 /*
3399 * Skip system tables, since index_create() would reject indexing them
3400 * concurrently (and it would likely fail if we tried).
3401 */
3402 if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
3403 IsCatalogRelationOid(relid))
3404 {
3405 if (!concurrent_warning)
3408 errmsg("cannot reindex system catalogs concurrently, skipping all")));
3409 concurrent_warning = true;
3410 continue;
3411 }
3412
3413 /*
3414 * If a new tablespace is set, check if this relation has to be
3415 * skipped.
3416 */
3418 {
3419 bool skip_rel = false;
3420
3421 /*
3422 * Mapped relations cannot be moved to different tablespaces (in
3423 * particular this eliminates all shared catalogs.).
3424 */
3425 if (RELKIND_HAS_STORAGE(classtuple->relkind) &&
3426 !RelFileNumberIsValid(classtuple->relfilenode))
3427 skip_rel = true;
3428
3429 /*
3430 * A system relation is always skipped, even with
3431 * allow_system_table_mods enabled.
3432 */
3433 if (IsSystemClass(relid, classtuple))
3434 skip_rel = true;
3435
3436 if (skip_rel)
3437 {
3438 if (!tablespace_warning)
3441 errmsg("cannot move system relations, skipping all")));
3442 tablespace_warning = true;
3443 continue;
3444 }
3445 }
3446
3447 /* Save the list of relation OIDs in private context */
3449
3450 /*
3451 * We always want to reindex pg_class first if it's selected to be
3452 * reindexed. This ensures that if there is any corruption in
3453 * pg_class' indexes, they will be fixed before we process any other
3454 * tables. This is critical because reindexing itself will try to
3455 * update pg_class.
3456 */
3457 if (relid == RelationRelationId)
3458 relids = lcons_oid(relid, relids);
3459 else
3460 relids = lappend_oid(relids, relid);
3461
3463 }
3464 table_endscan(scan);
3466
3467 /*
3468 * Process each relation listed in a separate transaction. Note that this
3469 * commits and then starts a new transaction immediately.
3470 */
3472
3474}
3475
3476/*
3477 * Error callback specific to ReindexPartitions().
3478 */
3479static void
3481{
3483
3485
3486 if (errinfo->relkind == RELKIND_PARTITIONED_TABLE)
3487 errcontext("while reindexing partitioned table \"%s.%s\"",
3488 errinfo->relnamespace, errinfo->relname);
3489 else if (errinfo->relkind == RELKIND_PARTITIONED_INDEX)
3490 errcontext("while reindexing partitioned index \"%s.%s\"",
3491 errinfo->relnamespace, errinfo->relname);
3492}
3493
3494/*
3495 * ReindexPartitions
3496 *
3497 * Reindex a set of partitions, per the partitioned index or table given
3498 * by the caller.
3499 */
3500static void
3502{
3503 List *partitions = NIL;
3504 char relkind = get_rel_relkind(relid);
3505 char *relname = get_rel_name(relid);
3506 char *relnamespace = get_namespace_name(get_rel_namespace(relid));
3508 List *inhoids;
3509 ListCell *lc;
3510 ErrorContextCallback errcallback;
3512
3514
3515 /*
3516 * Check if this runs in a transaction block, with an error callback to
3517 * provide more context under which a problem happens.
3518 */
3519 errinfo.relname = pstrdup(relname);
3520 errinfo.relnamespace = pstrdup(relnamespace);
3521 errinfo.relkind = relkind;
3522 errcallback.callback = reindex_error_callback;
3523 errcallback.arg = &errinfo;
3524 errcallback.previous = error_context_stack;
3525 error_context_stack = &errcallback;
3526
3528 relkind == RELKIND_PARTITIONED_TABLE ?
3529 "REINDEX TABLE" : "REINDEX INDEX");
3530
3531 /* Pop the error context stack */
3532 error_context_stack = errcallback.previous;
3533
3534 /*
3535 * Create special memory context for cross-transaction storage.
3536 *
3537 * Since it is a child of PortalContext, it will go away eventually even
3538 * if we suffer an error so there is no need for special abort cleanup
3539 * logic.
3540 */
3543
3544 /* ShareLock is enough to prevent schema modifications */
3546
3547 /*
3548 * The list of relations to reindex are the physical partitions of the
3549 * tree so discard any partitioned table or index.
3550 */
3551 foreach(lc, inhoids)
3552 {
3553 Oid partoid = lfirst_oid(lc);
3554 char partkind = get_rel_relkind(partoid);
3556
3557 /*
3558 * This discards partitioned tables, partitioned indexes and foreign
3559 * tables.
3560 */
3562 continue;
3563
3566
3567 /* Save partition OID */
3569 partitions = lappend_oid(partitions, partoid);
3571 }
3572
3573 /*
3574 * Process each partition listed in a separate transaction. Note that
3575 * this commits and then starts a new transaction immediately.
3576 */
3578
3579 /*
3580 * Clean up working storage --- note we must do this after
3581 * StartTransactionCommand, else we might be trying to delete the active
3582 * context!
3583 */
3585}
3586
3587/*
3588 * ReindexMultipleInternal
3589 *
3590 * Reindex a list of relations, each one being processed in its own
3591 * transaction. This commits the existing transaction immediately,
3592 * and starts a new transaction when finished.
3593 */
3594static void
3596{
3597 ListCell *l;
3598
3601
3602 foreach(l, relids)
3603 {
3604 Oid relid = lfirst_oid(l);
3605 char relkind;
3606 char relpersistence;
3607
3609
3610 /* functions in indexes may want a snapshot set */
3612
3613 /* check if the relation still exists */
3615 {
3618 continue;
3619 }
3620
3621 /*
3622 * Check permissions except when moving to database's default if a new
3623 * tablespace is chosen. Note that this check also happens in
3624 * ExecReindex(), but we do an extra check here as this runs across
3625 * multiple transactions.
3626 */
3629 {
3631
3634 if (aclresult != ACLCHECK_OK)
3637 }
3638
3639 relkind = get_rel_relkind(relid);
3640 relpersistence = get_rel_persistence(relid);
3641
3642 /*
3643 * Partitioned tables and indexes can never be processed directly, and
3644 * a list of their leaves should be built first.
3645 */
3646 Assert(!RELKIND_HAS_PARTITIONS(relkind));
3647
3648 if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
3649 relpersistence != RELPERSISTENCE_TEMP)
3650 {
3652
3655 if (ActiveSnapshotSet())
3657 /* ReindexRelationConcurrently() does the verbose output */
3658 }
3659 else if (relkind == RELKIND_INDEX)
3660 {
3662
3665 reindex_index(stmt, relid, false, relpersistence, &newparams);
3667 /* reindex_index() does the verbose output */
3668 }
3669 else
3670 {
3671 bool result;
3673
3676 result = reindex_relation(stmt, relid,
3679 &newparams);
3680
3681 if (result && (params->options & REINDEXOPT_VERBOSE) != 0)
3682 ereport(INFO,
3683 (errmsg("table \"%s.%s\" was reindexed",
3685 get_rel_name(relid))));
3686
3688 }
3689
3691 }
3692
3694}
3695
3696
3697/*
3698 * ReindexRelationConcurrently - process REINDEX CONCURRENTLY for given
3699 * relation OID
3700 *
3701 * 'relationOid' can either belong to an index, a table or a materialized
3702 * view. For tables and materialized views, all its indexes will be rebuilt,
3703 * excluding invalid indexes and any indexes used in exclusion constraints,
3704 * but including its associated toast table indexes. For indexes, the index
3705 * itself will be rebuilt.
3706 *
3707 * The locks taken on parent tables and involved indexes are kept until the
3708 * transaction is committed, at which point a session lock is taken on each
3709 * relation. Both of these protect against concurrent schema changes.
3710 *
3711 * Returns true if any indexes have been rebuilt (including toast table's
3712 * indexes, when relevant), otherwise returns false.
3713 *
3714 * NOTE: This cannot be used on temporary relations. A concurrent build would
3715 * cause issues with ON COMMIT actions triggered by the transactions of the
3716 * concurrent build. Temporary relations are not subject to concurrent
3717 * concerns, so there's no need for the more complicated concurrent build,
3718 * anyway, and a non-concurrent reindex is more efficient.
3719 */
3720static bool
3722{
3723 typedef struct ReindexIndexInfo
3724 {
3725 Oid indexId;
3726 Oid tableId;
3727 Oid amId;
3728 bool safe; /* for set_indexsafe_procflags */
3731 List *indexIds = NIL;
3732 List *newIndexIds = NIL;
3734 List *lockTags = NIL;
3735 ListCell *lc,
3736 *lc2;
3738 MemoryContext oldcontext;
3739 char relkind;
3740 char *relationName = NULL;
3741 char *relationNamespace = NULL;
3742 PGRUsage ru0;
3743 const int progress_index[] = {
3748 };
3750
3751 /*
3752 * Create a memory context that will survive forced transaction commits we
3753 * do below. Since it is a child of PortalContext, it will go away
3754 * eventually even if we suffer an error; there's no need for special
3755 * abort cleanup logic.
3756 */
3758 "ReindexConcurrent",
3760
3761 if ((params->options & REINDEXOPT_VERBOSE) != 0)
3762 {
3763 /* Save data needed by REINDEX VERBOSE in private context */
3765
3766 relationName = get_rel_name(relationOid);
3768
3770
3771 MemoryContextSwitchTo(oldcontext);
3772 }
3773
3774 relkind = get_rel_relkind(relationOid);
3775
3776 /*
3777 * Extract the list of indexes that are going to be rebuilt based on the
3778 * relation Oid given by caller.
3779 */
3780 switch (relkind)
3781 {
3782 case RELKIND_RELATION:
3783 case RELKIND_MATVIEW:
3784 case RELKIND_TOASTVALUE:
3785 {
3786 /*
3787 * In the case of a relation, find all its indexes including
3788 * toast indexes.
3789 */
3790 Relation heapRelation;
3791
3792 /* Save the list of relation OIDs in private context */
3794
3795 /* Track this relation for session locks */
3797
3798 MemoryContextSwitchTo(oldcontext);
3799
3800 if (IsCatalogRelationOid(relationOid))
3801 ereport(ERROR,
3803 errmsg("cannot reindex system catalogs concurrently")));
3804
3805 /* Open relation to get its indexes */
3806 if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3807 {
3808 heapRelation = try_table_open(relationOid,
3810 /* leave if relation does not exist */
3811 if (!heapRelation)
3812 break;
3813 }
3814 else
3815 heapRelation = table_open(relationOid,
3817
3818 if (OidIsValid(params->tablespaceOid) &&
3819 IsSystemRelation(heapRelation))
3820 ereport(ERROR,
3822 errmsg("cannot move system relation \"%s\"",
3823 RelationGetRelationName(heapRelation))));
3824
3825 /* Add all the valid indexes of relation to list */
3826 foreach(lc, RelationGetIndexList(heapRelation))
3827 {
3829 Relation indexRelation = index_open(cellOid,
3831
3832 if (!indexRelation->rd_index->indisvalid)
3835 errmsg("skipping reindex of invalid index \"%s.%s\"",
3838 errhint("Use DROP INDEX or REINDEX INDEX.")));
3839 else if (indexRelation->rd_index->indisexclusion)
3842 errmsg("cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping",
3845 else
3846 {
3848
3849 /* Save the list of relation OIDs in private context */
3851
3853 idx->indexId = cellOid;
3854 /* other fields set later */
3855
3857
3858 MemoryContextSwitchTo(oldcontext);
3859 }
3860
3861 index_close(indexRelation, NoLock);
3862 }
3863
3864 /* Also add the toast indexes */
3865 if (OidIsValid(heapRelation->rd_rel->reltoastrelid))
3866 {
3867 Oid toastOid = heapRelation->rd_rel->reltoastrelid;
3870
3871 /* Save the list of relation OIDs in private context */
3873
3874 /* Track this relation for session locks */
3876
3877 MemoryContextSwitchTo(oldcontext);
3878
3880 {
3882 Relation indexRelation = index_open(cellOid,
3884
3885 if (!indexRelation->rd_index->indisvalid)
3888 errmsg("skipping reindex of invalid index \"%s.%s\"",
3891 errhint("Use DROP INDEX or REINDEX INDEX.")));
3892 else
3893 {
3895
3896 /*
3897 * Save the list of relation OIDs in private
3898 * context
3899 */
3901
3903 idx->indexId = cellOid;
3905 /* other fields set later */
3906
3907 MemoryContextSwitchTo(oldcontext);
3908 }
3909
3910 index_close(indexRelation, NoLock);
3911 }
3912
3914 }
3915
3916 table_close(heapRelation, NoLock);
3917 break;
3918 }
3919 case RELKIND_INDEX:
3920 {
3921 Oid heapId = IndexGetRelation(relationOid,
3922 (params->options & REINDEXOPT_MISSING_OK) != 0);
3923 Relation heapRelation;
3925
3926 /* if relation is missing, leave */
3927 if (!OidIsValid(heapId))
3928 break;
3929
3931 ereport(ERROR,
3933 errmsg("cannot reindex system catalogs concurrently")));
3934
3935 /*
3936 * Don't allow reindex for an invalid index on TOAST table, as
3937 * if rebuilt it would not be possible to drop it. Match
3938 * error message in reindex_index().
3939 */
3940 if (IsToastNamespace(get_rel_namespace(relationOid)) &&
3941 !get_index_isvalid(relationOid))
3942 ereport(ERROR,
3944 errmsg("cannot reindex invalid index on TOAST table")));
3945
3946 /*
3947 * Check if parent relation can be locked and if it exists,
3948 * this needs to be done at this stage as the list of indexes
3949 * to rebuild is not complete yet, and REINDEXOPT_MISSING_OK
3950 * should not be used once all the session locks are taken.
3951 */
3952 if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3953 {
3954 heapRelation = try_table_open(heapId,
3956 /* leave if relation does not exist */
3957 if (!heapRelation)
3958 break;
3959 }
3960 else
3961 heapRelation = table_open(heapId,
3963
3964 if (OidIsValid(params->tablespaceOid) &&
3965 IsSystemRelation(heapRelation))
3966 ereport(ERROR,
3968 errmsg("cannot move system relation \"%s\"",
3969 get_rel_name(relationOid))));
3970
3971 table_close(heapRelation, NoLock);
3972
3973 /* Save the list of relation OIDs in private context */
3975
3976 /* Track the heap relation of this index for session locks */
3978
3979 /*
3980 * Save the list of relation OIDs in private context. Note
3981 * that invalid indexes are allowed here.
3982 */
3984 idx->indexId = relationOid;
3986 /* other fields set later */
3987
3988 MemoryContextSwitchTo(oldcontext);
3989 break;
3990 }
3991
3994 default:
3995 /* Return error if type of relation is not supported */
3996 ereport(ERROR,
3998 errmsg("cannot reindex this type of relation concurrently")));
3999 break;
4000 }
4001
4002 /*
4003 * Definitely no indexes, so leave. Any checks based on
4004 * REINDEXOPT_MISSING_OK should be done only while the list of indexes to
4005 * work on is built as the session locks taken before this transaction
4006 * commits will make sure that they cannot be dropped by a concurrent
4007 * session until this operation completes.
4008 */
4009 if (indexIds == NIL)
4010 return false;
4011
4012 /* It's not a shared catalog, so refuse to move it to shared tablespace */
4013 if (params->tablespaceOid == GLOBALTABLESPACE_OID)
4014 ereport(ERROR,
4016 errmsg("cannot move non-shared relation to tablespace \"%s\"",
4018
4020
4021 /*-----
4022 * Now we have all the indexes we want to process in indexIds.
4023 *
4024 * The phases now are:
4025 *
4026 * 1. create new indexes in the catalog
4027 * 2. build new indexes
4028 * 3. let new indexes catch up with tuples inserted in the meantime
4029 * 4. swap index names
4030 * 5. mark old indexes as dead
4031 * 6. drop old indexes
4032 *
4033 * We process each phase for all indexes before moving to the next phase,
4034 * for efficiency.
4035 */
4036
4037 /*
4038 * Phase 1 of REINDEX CONCURRENTLY
4039 *
4040 * Create a new index with the same properties as the old one, but it is
4041 * only registered in catalogs and will be built later. Then get session
4042 * locks on all involved tables. See analogous code in DefineIndex() for
4043 * more detailed comments.
4044 */
4045
4046 foreach(lc, indexIds)
4047 {
4048 char *concurrentName;
4052 Relation indexRel;
4053 Relation heapRel;
4054 Oid save_userid;
4055 int save_sec_context;
4056 int save_nestlevel;
4060
4061 indexRel = index_open(idx->indexId, ShareUpdateExclusiveLock);
4062 heapRel = table_open(indexRel->rd_index->indrelid,
4064
4065 /*
4066 * Switch to the table owner's userid, so that any index functions are
4067 * run as that user. Also lock down security-restricted operations
4068 * and arrange to make GUC variable changes local to this command.
4069 */
4070 GetUserIdAndSecContext(&save_userid, &save_sec_context);
4071 SetUserIdAndSecContext(heapRel->rd_rel->relowner,
4072 save_sec_context | SECURITY_RESTRICTED_OPERATION);
4073 save_nestlevel = NewGUCNestLevel();
4075
4076 /* determine safety of this index for set_indexsafe_procflags */
4077 idx->safe = (RelationGetIndexExpressions(indexRel) == NIL &&
4078 RelationGetIndexPredicate(indexRel) == NIL);
4079
4080#ifdef USE_INJECTION_POINTS
4081 if (idx->safe)
4082 INJECTION_POINT("reindex-conc-index-safe", NULL);
4083 else
4084 INJECTION_POINT("reindex-conc-index-not-safe", NULL);
4085#endif
4086
4087 idx->tableId = RelationGetRelid(heapRel);
4088 idx->amId = indexRel->rd_rel->relam;
4089
4090 /* This function shouldn't be called for temporary relations. */
4091 if (indexRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
4092 elog(ERROR, "cannot reindex a temporary table concurrently");
4093
4095
4097 progress_vals[1] = 0; /* initializing */
4098 progress_vals[2] = idx->indexId;
4099 progress_vals[3] = idx->amId;
4101
4102 /* Choose a temporary relation name for the new index */
4104 NULL,
4105 "ccnew",
4106 get_rel_namespace(indexRel->rd_index->indrelid),
4107 false);
4108
4109 /* Choose the new tablespace, indexes of toast tables are not moved */
4110 if (OidIsValid(params->tablespaceOid) &&
4111 heapRel->rd_rel->relkind != RELKIND_TOASTVALUE)
4112 tablespaceid = params->tablespaceOid;
4113 else
4114 tablespaceid = indexRel->rd_rel->reltablespace;
4115
4116 /* Create new index definition based on given index */
4117 newIndexId = index_create_copy(heapRel,
4121 idx->indexId,
4124
4125 /*
4126 * Now open the relation of the new index, a session-level lock is
4127 * also needed on it.
4128 */
4130
4131 /*
4132 * Save the list of OIDs and locks in private context
4133 */
4135
4137 newidx->indexId = newIndexId;
4138 newidx->safe = idx->safe;
4139 newidx->tableId = idx->tableId;
4140 newidx->amId = idx->amId;
4141
4143
4144 /*
4145 * Save lockrelid to protect each relation from drop then close
4146 * relations. The lockrelid on parent relation is not taken here to
4147 * avoid multiple locks taken on the same relation, instead we rely on
4148 * parentRelationIds built earlier.
4149 */
4151 *lockrelid = indexRel->rd_lockInfo.lockRelId;
4154 *lockrelid = newIndexRel->rd_lockInfo.lockRelId;
4156
4157 MemoryContextSwitchTo(oldcontext);
4158
4159 index_close(indexRel, NoLock);
4161
4162 /* Roll back any GUC changes executed by index functions */
4163 AtEOXact_GUC(false, save_nestlevel);
4164
4165 /* Restore userid and security context */
4166 SetUserIdAndSecContext(save_userid, save_sec_context);
4167
4168 table_close(heapRel, NoLock);
4169
4170 /*
4171 * If a statement is available, telling that this comes from a REINDEX
4172 * command, collect the new index for event triggers.
4173 */
4174 if (stmt)
4175 {
4176 ObjectAddress address;
4177
4181 (const Node *) stmt);
4182 }
4183 }
4184
4185 /*
4186 * Save the heap lock for following visibility checks with other backends
4187 * might conflict with this session.
4188 */
4189 foreach(lc, heapRelationIds)
4190 {
4194
4195 /* Save the list of locks in private context */
4197
4198 /* Add lockrelid of heap relation to the list of locked relations */
4200 *lockrelid = heapRelation->rd_lockInfo.lockRelId;
4202
4204
4205 /* Save the LOCKTAG for this parent relation for the wait phase */
4208
4209 MemoryContextSwitchTo(oldcontext);
4210
4211 /* Close heap relation */
4212 table_close(heapRelation, NoLock);
4213 }
4214
4215 /* Get a session-level lock on each table. */
4216 foreach(lc, relationLocks)
4217 {
4219
4221 }
4222
4226
4227 /*
4228 * Because we don't take a snapshot in this transaction, there's no need
4229 * to set the PROC_IN_SAFE_IC flag here.
4230 */
4231
4232 /*
4233 * Phase 2 of REINDEX CONCURRENTLY
4234 *
4235 * Build the new indexes in a separate transaction for each index to avoid
4236 * having open transactions for an unnecessary long time. But before
4237 * doing that, wait until no running transactions could have the table of
4238 * the index open with the old list of indexes. See "phase 2" in
4239 * DefineIndex() for more details.
4240 */
4241
4246
4247 foreach(lc, newIndexIds)
4248 {
4250
4251 /* Start new transaction for this index's concurrent build */
4253
4254 /*
4255 * Check for user-requested abort. This is inside a transaction so as
4256 * xact.c does not issue a useless WARNING, and ensures that
4257 * session-level locks are cleaned up on abort.
4258 */
4260
4261 /* Tell concurrent indexing to ignore us, if index qualifies */
4262 if (newidx->safe)
4264
4265 /* Set ActiveSnapshot since functions in the indexes may need it */
4267
4268 /*
4269 * Update progress for the index to build, with the correct parent
4270 * table involved.
4271 */
4275 progress_vals[2] = newidx->indexId;
4276 progress_vals[3] = newidx->amId;
4278
4279 /* Perform concurrent build of new index */
4280 index_concurrently_build(newidx->tableId, newidx->indexId);
4281
4284 }
4285
4287
4288 /*
4289 * Because we don't take a snapshot or Xid in this transaction, there's no
4290 * need to set the PROC_IN_SAFE_IC flag here.
4291 */
4292
4293 /*
4294 * Phase 3 of REINDEX CONCURRENTLY
4295 *
4296 * During this phase the old indexes catch up with any new tuples that
4297 * were created during the previous phase. See "phase 3" in DefineIndex()
4298 * for more details.
4299 */
4300
4305
4306 foreach(lc, newIndexIds)
4307 {
4310 Snapshot snapshot;
4311
4313
4314 /*
4315 * Check for user-requested abort. This is inside a transaction so as
4316 * xact.c does not issue a useless WARNING, and ensures that
4317 * session-level locks are cleaned up on abort.
4318 */
4320
4321 /* Tell concurrent indexing to ignore us, if index qualifies */
4322 if (newidx->safe)
4324
4325 /*
4326 * Take the "reference snapshot" that will be used by validate_index()
4327 * to filter candidate tuples.
4328 */
4330 PushActiveSnapshot(snapshot);
4331
4332 /*
4333 * Update progress for the index to build, with the correct parent
4334 * table involved.
4335 */
4339 progress_vals[2] = newidx->indexId;
4340 progress_vals[3] = newidx->amId;
4342
4343 validate_index(newidx->tableId, newidx->indexId, snapshot);
4344
4345 /*
4346 * We can now do away with our active snapshot, we still need to save
4347 * the xmin limit to wait for older snapshots.
4348 */
4349 limitXmin = snapshot->xmin;
4350
4352 UnregisterSnapshot(snapshot);
4353
4354 /*
4355 * To ensure no deadlocks, we must commit and start yet another
4356 * transaction, and do our wait before any snapshot has been taken in
4357 * it.
4358 */
4361
4362 /*
4363 * The index is now valid in the sense that it contains all currently
4364 * interesting tuples. But since it might not contain tuples deleted
4365 * just before the reference snap was taken, we have to wait out any
4366 * transactions that might have older snapshots.
4367 *
4368 * Because we don't take a snapshot or Xid in this transaction,
4369 * there's no need to set the PROC_IN_SAFE_IC flag here.
4370 */
4374
4376 }
4377
4378 /*
4379 * Phase 4 of REINDEX CONCURRENTLY
4380 *
4381 * Now that the new indexes have been validated, swap each new index with
4382 * its corresponding old index.
4383 *
4384 * We mark the new indexes as valid and the old indexes as not valid at
4385 * the same time to make sure we only get constraint violations from the
4386 * indexes with the correct names.
4387 */
4388
4389 INJECTION_POINT("reindex-relation-concurrently-before-swap", NULL);
4391
4392 /*
4393 * Because this transaction only does catalog manipulations and doesn't do
4394 * any index operations, we can set the PROC_IN_SAFE_IC flag here
4395 * unconditionally.
4396 */
4398
4400 {
4403 char *oldName;
4404
4405 /*
4406 * Check for user-requested abort. This is inside a transaction so as
4407 * xact.c does not issue a useless WARNING, and ensures that
4408 * session-level locks are cleaned up on abort.
4409 */
4411
4412 /* Choose a relation name for old index */
4414 NULL,
4415 "ccold",
4416 get_rel_namespace(oldidx->tableId),
4417 false);
4418
4419 /*
4420 * Swapping the indexes might involve TOAST table access, so ensure we
4421 * have a valid snapshot.
4422 */
4424
4425 /*
4426 * Swap old index with the new one. This also marks the new one as
4427 * valid and the old one as not valid.
4428 */
4429 index_concurrently_swap(newidx->indexId, oldidx->indexId, oldName);
4430
4432
4433 /*
4434 * Invalidate the relcache for the table, so that after this commit
4435 * all sessions will refresh any cached plans that might reference the
4436 * index.
4437 */
4439
4440 /*
4441 * CCI here so that subsequent iterations see the oldName in the
4442 * catalog and can choose a nonconflicting name for their oldName.
4443 * Otherwise, this could lead to conflicts if a table has two indexes
4444 * whose names are equal for the first NAMEDATALEN-minus-a-few
4445 * characters.
4446 */
4448 }
4449
4450 /* Commit this transaction and make index swaps visible */
4453
4454 /*
4455 * While we could set PROC_IN_SAFE_IC if all indexes qualified, there's no
4456 * real need for that, because we only acquire an Xid after the wait is
4457 * done, and that lasts for a very short period.
4458 */
4459
4460 /*
4461 * Phase 5 of REINDEX CONCURRENTLY
4462 *
4463 * Mark the old indexes as dead. First we must wait until no running
4464 * transaction could be using the index for a query. See also
4465 * index_drop() for more details.
4466 */
4467
4468 INJECTION_POINT("reindex-relation-concurrently-before-set-dead", NULL);
4472
4473 foreach(lc, indexIds)
4474 {
4476
4477 /*
4478 * Check for user-requested abort. This is inside a transaction so as
4479 * xact.c does not issue a useless WARNING, and ensures that
4480 * session-level locks are cleaned up on abort.
4481 */
4483
4484 /*
4485 * Updating pg_index might involve TOAST table access, so ensure we
4486 * have a valid snapshot.
4487 */
4489
4490 index_concurrently_set_dead(oldidx->tableId, oldidx->indexId);
4491
4493 }
4494
4495 /* Commit this transaction to make the updates visible. */
4498
4499 /*
4500 * While we could set PROC_IN_SAFE_IC if all indexes qualified, there's no
4501 * real need for that, because we only acquire an Xid after the wait is
4502 * done, and that lasts for a very short period.
4503 */
4504
4505 /*
4506 * Phase 6 of REINDEX CONCURRENTLY
4507 *
4508 * Drop the old indexes.
4509 */
4510
4514
4516
4517 {
4519
4520 foreach(lc, indexIds)
4521 {
4523 ObjectAddress object;
4524
4525 object.classId = RelationRelationId;
4526 object.objectId = idx->indexId;
4527 object.objectSubId = 0;
4528
4529 add_exact_object_address(&object, objects);
4530 }
4531
4532 /*
4533 * Use PERFORM_DELETION_CONCURRENT_LOCK so that index_drop() uses the
4534 * right lock level.
4535 */
4538 }
4539
4542
4543 /*
4544 * Finally, release the session-level lock on the table.
4545 */
4546 foreach(lc, relationLocks)
4547 {
4549
4551 }
4552
4553 /* Start a new transaction to finish process properly */
4555
4556 /* Log what we did */
4557 if ((params->options & REINDEXOPT_VERBOSE) != 0)
4558 {
4559 if (relkind == RELKIND_INDEX)
4560 ereport(INFO,
4561 (errmsg("index \"%s.%s\" was reindexed",
4563 errdetail("%s.",
4564 pg_rusage_show(&ru0))));
4565 else
4566 {
4567 foreach(lc, newIndexIds)
4568 {
4570 Oid indOid = idx->indexId;
4571
4572 ereport(INFO,
4573 (errmsg("index \"%s.%s\" was reindexed",
4575 get_rel_name(indOid))));
4576 /* Don't show rusage here, since it's not per index. */
4577 }
4578
4579 ereport(INFO,
4580 (errmsg("table \"%s.%s\" was reindexed",
4582 errdetail("%s.",
4583 pg_rusage_show(&ru0))));
4584 }
4585 }
4586
4588
4590
4591 return true;
4592}
4593
4594/*
4595 * Insert or delete an appropriate pg_inherits tuple to make the given index
4596 * be a partition of the indicated parent index.
4597 *
4598 * This also corrects the pg_depend information for the affected index.
4599 */
4600void
4602{
4604 ScanKeyData key[2];
4605 SysScanDesc scan;
4606 Oid partRelid = RelationGetRelid(partitionIdx);
4607 HeapTuple tuple;
4608 bool fix_dependencies;
4609
4610 /* Make sure this is an index */
4611 Assert(partitionIdx->rd_rel->relkind == RELKIND_INDEX ||
4612 partitionIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX);
4613
4614 /*
4615 * Scan pg_inherits for rows linking our index to some parent.
4616 */
4618 ScanKeyInit(&key[0],
4622 ScanKeyInit(&key[1],
4625 Int32GetDatum(1));
4627 NULL, 2, key);
4628 tuple = systable_getnext(scan);
4629
4630 if (!HeapTupleIsValid(tuple))
4631 {
4632 if (parentOid == InvalidOid)
4633 {
4634 /*
4635 * No pg_inherits row, and no parent wanted: nothing to do in this
4636 * case.
4637 */
4638 fix_dependencies = false;
4639 }
4640 else
4641 {
4643 fix_dependencies = true;
4644 }
4645 }
4646 else
4647 {
4649
4650 if (parentOid == InvalidOid)
4651 {
4652 /*
4653 * There exists a pg_inherits row, which we want to clear; do so.
4654 */
4656 fix_dependencies = true;
4657 }
4658 else
4659 {
4660 /*
4661 * A pg_inherits row exists. If it's the same we want, then we're
4662 * good; if it differs, that amounts to a corrupt catalog and
4663 * should not happen.
4664 */
4665 if (inhForm->inhparent != parentOid)
4666 {
4667 /* unexpected: we should not get called in this case */
4668 elog(ERROR, "bogus pg_inherit row: inhrelid %u inhparent %u",
4669 inhForm->inhrelid, inhForm->inhparent);
4670 }
4671
4672 /* already in the right state */
4673 fix_dependencies = false;
4674 }
4675 }
4676
4677 /* done with pg_inherits */
4678 systable_endscan(scan);
4680
4681 /* set relhassubclass if an index partition has been added to the parent */
4682 if (OidIsValid(parentOid))
4683 {
4686 }
4687
4688 /* set relispartition correctly on the partition */
4690
4691 if (fix_dependencies)
4692 {
4693 /*
4694 * Insert/delete pg_depend rows. If setting a parent, add PARTITION
4695 * dependencies on the parent index and the table; if removing a
4696 * parent, delete PARTITION dependencies.
4697 */
4698 if (OidIsValid(parentOid))
4699 {
4701 ObjectAddress parentIdx;
4702 ObjectAddress partitionTbl;
4703
4707 partitionIdx->rd_index->indrelid);
4708 recordDependencyOn(&partIdx, &parentIdx,
4710 recordDependencyOn(&partIdx, &partitionTbl,
4712 }
4713 else
4714 {
4721 }
4722
4723 /* make our updates visible */
4725 }
4726}
4727
4728/*
4729 * Subroutine of IndexSetParentIndex to update the relispartition flag of the
4730 * given index to the given value.
4731 */
4732static void
4751
4752/*
4753 * Set the PROC_IN_SAFE_IC flag in MyProc->statusFlags.
4754 *
4755 * When doing concurrent index builds, we can set this flag
4756 * to tell other processes concurrently running CREATE
4757 * INDEX CONCURRENTLY or REINDEX CONCURRENTLY to ignore us when
4758 * doing their waits for concurrent snapshots. On one hand it
4759 * avoids pointlessly waiting for a process that's not interesting
4760 * anyway; but more importantly it avoids deadlocks in some cases.
4761 *
4762 * This can be done safely only for indexes that don't execute any
4763 * expressions that could access other tables, so index must not be
4764 * expressional nor partial. Caller is responsible for only calling
4765 * this routine when that assumption holds true.
4766 *
4767 * (The flag is reset automatically at transaction end, so it must be
4768 * set for each transaction.)
4769 */
4770static inline void
4772{
4773 /*
4774 * This should only be called before installing xid or xmin in MyProc;
4775 * otherwise, concurrent processes could see an Xmin that moves backwards.
4776 */
4779
4784}
Datum idx(PG_FUNCTION_ARGS)
Definition _int_op.c:263
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:3902
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4156
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4105
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:166
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:894
#define IS_HIGHBIT_SET(ch)
Definition c.h:1303
#define Assert(condition)
Definition c.h:1002
int64_t int64
Definition c.h:680
int16_t int16
Definition c.h:678
uint16_t uint16
Definition c.h:682
uint32 TransactionId
Definition c.h:795
#define OidIsValid(objectId)
Definition c.h:917
bool IsToastNamespace(Oid namespaceId)
Definition catalog.c:277
bool IsSystemRelation(Relation relation)
Definition catalog.c:74
bool IsCatalogRelationOid(Oid relid)
Definition catalog.c:123
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition catalog.c:86
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
bool contain_mutable_functions_after_planning(Expr *expr)
Definition clauses.c:519
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:1323
ErrorContextCallback * error_context_stack
Definition elog.c:100
int errcode(int sqlerrcode)
Definition elog.c:875
#define errcontext
Definition elog.h:200
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:37
#define DEBUG1
Definition elog.h:31
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define NOTICE
Definition elog.h:36
#define INFO
Definition elog.h:35
#define ereport(elevel,...)
Definition elog.h:152
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, const Node *parsetree)
#define palloc_object(type)
Definition fe_memutils.h:89
#define palloc_array(type, count)
Definition fe_memutils.h:91
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 * OidOutputFunctionCall(Oid functionId, Datum val)
Definition fmgr.c:1764
char * format_type_be(Oid type_oid)
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:515
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
bool allowSystemTableMods
Definition globals.c:132
Oid MyDatabaseTableSpace
Definition globals.c:98
Oid MyDatabaseId
Definition globals.c:96
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:1435
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:686
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define stmt
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, uint16 flags, uint16 constr_flags, bool allow_system_table_mods, bool is_internal, Oid *constraintId)
Definition index.c:730
void validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
Definition index.c:3371
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition index.c:3604
void index_concurrently_set_dead(Oid heapId, Oid indexId)
Definition index.c:1841
void index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
Definition index.c:1570
void index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
Definition index.c:3524
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:2555
bool reindex_relation(const ReindexStmt *stmt, Oid relid, int flags, const ReindexParams *params)
Definition index.c:3969
IndexInfo * BuildIndexInfo(Relation index)
Definition index.c:2446
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:1503
Oid index_create_copy(Relation heapRelation, uint16 flags, Oid oldIndexId, Oid tablespaceOid, const char *newName)
Definition index.c:1306
void reindex_index(const ReindexStmt *stmt, Oid indexId, bool skip_constraint_checks, char persistence, const ReindexParams *params)
Definition index.c:3629
#define INDEX_CREATE_SUPPRESS_PROGRESS
Definition index.h:74
#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:166
#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:103
#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:99
#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:100
#define INDEX_CREATE_CONCURRENT
Definition index.h:70
#define REINDEXOPT_VERBOSE
Definition index.h:47
#define REINDEX_REL_CHECK_CONSTRAINTS
Definition index.h:168
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:178
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:134
static bool ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const ReindexParams *params)
Definition indexcmds.c:3721
void ExecReindex(ParseState *pstate, const ReindexStmt *stmt, bool isTopLevel)
Definition indexcmds.c:2977
static void set_indexsafe_procflags(void)
Definition indexcmds.c:4771
char * ChooseRelationName(const char *name1, const char *name2, const char *label, Oid namespaceid, bool isconstraint)
Definition indexcmds.c:2644
static void reindex_error_callback(void *arg)
Definition indexcmds.c:3480
static List * ChooseIndexColumnNames(Relation rel, const List *indexElems)
Definition indexcmds.c:2802
static void ReindexIndex(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel)
Definition indexcmds.c:3072
void IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
Definition indexcmds.c:4601
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition indexcmds.c:2556
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition indexcmds.c:2381
static char * ChooseIndexNameAddition(const List *colnames)
Definition indexcmds.c:2767
static void ReindexMultipleTables(const ReindexStmt *stmt, const ReindexParams *params)
Definition indexcmds.c:3261
static bool CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts)
Definition indexcmds.c:373
static void update_relispartition(Oid relationId, bool newval)
Definition indexcmds.c:4733
bool CheckIndexCompatible(Oid oldId, const char *accessMethodName, const List *attributeList, const List *exclusionOpNames, bool isWithoutOverlaps)
Definition indexcmds.c:189
void WaitForOlderSnapshots(TransactionId limitXmin, bool progress)
Definition indexcmds.c:446
static bool ChooseIndexExpressionName_walker(Node *node, CIEN_context *context)
Definition indexcmds.c:2885
Oid ResolveOpClass(const List *opclass, Oid attrType, const char *accessMethodName, Oid accessMethodId)
Definition indexcmds.c:2296
static void ReindexPartitions(const ReindexStmt *stmt, Oid relid, const ReindexParams *params, bool isTopLevel)
Definition indexcmds.c:3501
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:555
static Oid ReindexTable(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel)
Definition indexcmds.c:3202
static void CheckPredicate(Expr *predicate)
Definition indexcmds.c:1864
static void ReindexMultipleInternal(const ReindexStmt *stmt, const List *relids, const ReindexParams *params)
Definition indexcmds.c:3595
static void RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition indexcmds.c:3126
static char * ChooseIndexExpressionName(Relation rel, Node *indexExpr)
Definition indexcmds.c:2865
void GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype, Oid *opid, StrategyNumber *strat)
Definition indexcmds.c:2483
static char * ChooseIndexName(const char *tabname, Oid namespaceId, const List *colnames, const List *exclusionOpNames, bool primary, bool isconstraint)
Definition indexcmds.c:2712
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:1891
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:1688
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:4725
#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:2242
Oid get_opclass_method(Oid opclass)
Definition lsyscache.c:1512
char get_rel_persistence(Oid relid)
Definition lsyscache.c:2392
bool get_index_isvalid(Oid index_oid)
Definition lsyscache.c:3939
Oid get_opclass_input_type(Oid opclass)
Definition lsyscache.c:1464
Oid get_opclass_family(Oid opclass)
Definition lsyscache.c:1442
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:1487
char * get_database_name(Oid dbid)
Definition lsyscache.c:1392
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3223
char * get_opname(Oid opno)
Definition lsyscache.c:1610
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1196
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2317
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2266
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1585
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:1553
char * get_func_name(Oid funcid)
Definition lsyscache.c:1922
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3397
Oid get_opfamily_method(Oid opfid)
Definition lsyscache.c:1536
Oid getBaseType(Oid typid)
Definition lsyscache.c:2837
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3682
Oid get_commutator(Oid opno)
Definition lsyscache.c:1823
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition lsyscache.c:1658
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_EXCLUSIVE
Definition lwlock.h:104
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:1212
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc(Size size)
Definition mcxt.c:1390
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:475
MemoryContext PortalContext
Definition mcxt.c:176
#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:486
#define SECURITY_RESTRICTED_OPERATION
Definition miscadmin.h:322
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
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 expression_tree_walker(n, w, c)
Definition nodeFuncs.h:153
#define IsA(nodeptr, _type_)
Definition nodes.h:162
static char * errmsg
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
TYPCATEGORY TypeCategory(Oid type)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
bool IsPreferredType(TYPCATEGORY category, Oid type)
char TYPCATEGORY
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:497
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:922
@ 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:51
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition pg_depend.c:364
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:550
#define list_make1_oid(x1)
Definition pg_list.h:274
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:375
#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:263
#define snprintf
Definition port.h:261
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 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:383
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define PointerGetDatum(X)
Definition postgres.h:354
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define PROC_IN_SAFE_IC
Definition proc.h:63
#define PROC_IN_VACUUM
Definition proc.h:62
#define PROC_IS_AUTOVACUUM
Definition proc.h:61
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:129
#define PROGRESS_CREATEIDX_PHASE_BUILD
Definition progress.h:123
#define PROGRESS_CREATEIDX_PARTITIONS_DONE
Definition progress.h:118
#define PROGRESS_CREATEIDX_PHASE_WAIT_1
Definition progress.h:122
#define PROGRESS_CREATEIDX_COMMAND_CREATE_CONCURRENTLY
Definition progress.h:140
#define PROGRESS_CREATEIDX_ACCESS_METHOD_OID
Definition progress.h:112
#define PROGRESS_WAITFOR_DONE
Definition progress.h:146
#define PROGRESS_CREATEIDX_PHASE_WAIT_3
Definition progress.h:128
#define PROGRESS_WAITFOR_TOTAL
Definition progress.h:145
#define PROGRESS_CREATEIDX_COMMAND_REINDEX_CONCURRENTLY
Definition progress.h:142
#define PROGRESS_CREATEIDX_COMMAND_CREATE
Definition progress.h:139
#define PROGRESS_WAITFOR_CURRENT_PID
Definition progress.h:147
#define PROGRESS_CREATEIDX_PHASE_WAIT_2
Definition progress.h:124
#define PROGRESS_CREATEIDX_PHASE
Definition progress.h:113
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN
Definition progress.h:125
#define PROGRESS_CREATEIDX_PHASE_WAIT_5
Definition progress.h:130
#define PROGRESS_CREATEIDX_INDEX_OID
Definition progress.h:111
#define PROGRESS_CREATEIDX_PARTITIONS_TOTAL
Definition progress.h:117
#define PROGRESS_CREATEIDX_COMMAND
Definition progress.h:110
char * format_operator(Oid operator_oid)
Definition regproc.c:801
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetDescr(relation)
Definition rel.h:542
#define RelationGetRelationName(relation)
Definition rel.h:550
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:678
#define RelationGetNamespace(relation)
Definition rel.h:557
List * RelationGetIndexList(Relation relation)
Definition relcache.c:4846
List * RelationGetIndexPredicate(Relation relation)
Definition relcache.c:5220
List * RelationGetIndexExpressions(Relation relation)
Definition relcache.c:5107
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition relcache.c:5663
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:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:48
PGPROC * MyProc
Definition proc.c:71
PROC_HDR * ProcGlobal
Definition proc.c:74
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
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
StringInfo buf
Definition indexcmds.c:80
Relation rel
Definition indexcmds.c:79
Oid consttype
Definition primnodes.h:333
char * defname
Definition parsenodes.h:863
ParseLoc location
Definition parsenodes.h:867
struct ErrorContextCallback * previous
Definition elog.h:299
void(* callback)(void *arg)
Definition elog.h:300
Oid funcid
Definition primnodes.h:770
ItemPointerData t_self
Definition htup.h:65
char * indexcolname
Definition parsenodes.h:832
uint16 * ii_ExclusionStrats
Definition execnodes.h:206
int ii_NumIndexAttrs
Definition execnodes.h:181
Oid * ii_ExclusionOps
Definition execnodes.h:202
int ii_NumIndexKeyAttrs
Definition execnodes.h:183
List * ii_Expressions
Definition execnodes.h:192
Oid * ii_ExclusionProcs
Definition execnodes.h:204
AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS]
Definition execnodes.h:189
List * ii_Predicate
Definition execnodes.h:197
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:133
Definition proc.h:179
TransactionId xmin
Definition proc.h:242
uint8 statusFlags
Definition proc.h:210
int pgxactoff
Definition proc.h:207
TransactionId xid
Definition proc.h:237
uint8 * statusFlags
Definition proc.h:456
char * relname
Definition primnodes.h:84
char * relnamespace
Definition indexcmds.c:146
Oid tablespaceOid
Definition index.h:42
uint32 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
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270
Index varlevelsup
Definition primnodes.h:295
Definition c.h:874
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27
HeapTuple SearchSysCacheLockedCopy1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:400
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache3(SysCacheIdentifier cacheId, Datum key1, Datum key2, Datum key3)
Definition syscache.c:241
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition syscache.c:476
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:626
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
#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:1061
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition tablecmds.c:4507
void SetRelationHasSubclass(Oid relationId, bool relhassubclass)
Definition tablecmds.c:3725
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:1130
void PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
Definition xact.c:3701
void StartTransactionCommand(void)
Definition xact.c:3112
void CommitTransactionCommand(void)
Definition xact.c:3210