PostgreSQL Source Code git master
Loading...
Searching...
No Matches
index.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * index.c
4 * code to create and destroy POSTGRES index relations
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/catalog/index.c
12 *
13 *
14 * INTERFACE ROUTINES
15 * index_create() - Create a cataloged index relation
16 * index_drop() - Removes index relation from catalogs
17 * BuildIndexInfo() - Prepare to insert index tuples
18 * FormIndexDatum() - Construct datum vector for one index tuple
19 *
20 *-------------------------------------------------------------------------
21 */
22#include "postgres.h"
23
24#include <unistd.h>
25
26#include "access/amapi.h"
27#include "access/attmap.h"
28#include "access/heapam.h"
29#include "access/multixact.h"
30#include "access/relscan.h"
31#include "access/tableam.h"
33#include "access/transam.h"
35#include "access/xact.h"
36#include "bootstrap/bootstrap.h"
38#include "catalog/catalog.h"
39#include "catalog/dependency.h"
40#include "catalog/heap.h"
41#include "catalog/index.h"
43#include "catalog/partition.h"
44#include "catalog/pg_am.h"
48#include "catalog/pg_inherits.h"
49#include "catalog/pg_opclass.h"
50#include "catalog/pg_operator.h"
52#include "catalog/pg_trigger.h"
53#include "catalog/pg_type.h"
54#include "catalog/storage.h"
57#include "commands/progress.h"
58#include "commands/tablecmds.h"
59#include "commands/trigger.h"
60#include "executor/executor.h"
61#include "miscadmin.h"
62#include "nodes/makefuncs.h"
63#include "nodes/nodeFuncs.h"
64#include "optimizer/optimizer.h"
65#include "parser/parser.h"
66#include "pgstat.h"
69#include "storage/bufmgr.h"
70#include "storage/lmgr.h"
71#include "storage/predicate.h"
72#include "storage/smgr.h"
73#include "utils/builtins.h"
74#include "utils/fmgroids.h"
75#include "utils/guc.h"
76#include "utils/inval.h"
77#include "utils/lsyscache.h"
78#include "utils/memutils.h"
79#include "utils/pg_rusage.h"
80#include "utils/rel.h"
81#include "utils/snapmgr.h"
82#include "utils/syscache.h"
83#include "utils/tuplesort.h"
84
85/* Potentially set by pg_upgrade_support functions */
89
90/*
91 * Pointer-free representation of variables used when reindexing system
92 * catalogs; we use this to propagate those values to parallel workers.
93 */
101
102/* non-export function prototypes */
103static bool relationHasPrimaryKey(Relation rel);
105 const IndexInfo *indexInfo,
106 const List *indexColNames,
108 const Oid *collationIds,
109 const Oid *opclassIds);
110static void InitializeAttributeOids(Relation indexRelation,
111 int numatts, Oid indexoid);
112static void AppendAttributeTuples(Relation indexRelation, const Datum *attopts, const NullableDatum *stattargets);
113static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
115 const IndexInfo *indexInfo,
116 const Oid *collationOids,
117 const Oid *opclassOids,
118 const int16 *coloptions,
119 bool primary,
120 bool isexclusion,
121 bool immediate,
122 bool isvalid,
123 bool isready);
124static void index_update_stats(Relation rel,
125 bool hasindex,
126 double reltuples);
127static void IndexCheckExclusion(Relation heapRelation,
128 Relation indexRelation,
129 IndexInfo *indexInfo);
130static bool validate_index_callback(ItemPointer itemptr, void *opaque);
131static bool ReindexIsCurrentlyProcessingIndex(Oid indexOid);
132static void SetReindexProcessing(Oid heapOid, Oid indexOid);
133static void ResetReindexProcessing(void);
134static void SetReindexPending(List *indexes);
135static void RemoveReindexPending(Oid indexOid);
136
137
138/*
139 * relationHasPrimaryKey
140 * See whether an existing relation has a primary key.
141 *
142 * Caller must have suitable lock on the relation.
143 *
144 * Note: we intentionally do not check indisvalid here; that's because this
145 * is used to enforce the rule that there can be only one indisprimary index,
146 * and we want that to be true even if said index is invalid.
147 */
148static bool
150{
151 bool result = false;
154
155 /*
156 * Get the list of index OIDs for the table from the relcache, and look up
157 * each one in the pg_index syscache until we find one marked primary key
158 * (hopefully there isn't more than one such).
159 */
161
162 foreach(indexoidscan, indexoidlist)
163 {
164 Oid indexoid = lfirst_oid(indexoidscan);
166
168 if (!HeapTupleIsValid(indexTuple)) /* should not happen */
169 elog(ERROR, "cache lookup failed for index %u", indexoid);
172 if (result)
173 break;
174 }
175
177
178 return result;
179}
180
181/*
182 * index_check_primary_key
183 * Apply special checks needed before creating a PRIMARY KEY index
184 *
185 * This processing used to be in DefineIndex(), but has been split out
186 * so that it can be applied during ALTER TABLE ADD PRIMARY KEY USING INDEX.
187 *
188 * We check for a pre-existing primary key, and that all columns of the index
189 * are simple column references (not expressions), and that all those
190 * columns are marked NOT NULL. If not, fail.
191 *
192 * We used to automatically change unmarked columns to NOT NULL here by doing
193 * our own local ALTER TABLE command. But that doesn't work well if we're
194 * executing one subcommand of an ALTER TABLE: the operations may not get
195 * performed in the right order overall. Now we expect that the parser
196 * inserted any required ALTER TABLE SET NOT NULL operations before trying
197 * to create a primary-key index.
198 *
199 * Caller had better have at least ShareLock on the table, else the not-null
200 * checking isn't trustworthy.
201 */
202void
204 const IndexInfo *indexInfo,
205 bool is_alter_table,
206 const IndexStmt *stmt)
207{
208 int i;
209
210 /*
211 * If ALTER TABLE or CREATE TABLE .. PARTITION OF, check that there isn't
212 * already a PRIMARY KEY. In CREATE TABLE for an ordinary relation, we
213 * have faith that the parser rejected multiple pkey clauses; and CREATE
214 * INDEX doesn't have a way to say PRIMARY KEY, so it's no problem either.
215 */
216 if ((is_alter_table || heapRel->rd_rel->relispartition) &&
217 relationHasPrimaryKey(heapRel))
218 {
221 errmsg("multiple primary keys for table \"%s\" are not allowed",
222 RelationGetRelationName(heapRel))));
223 }
224
225 /*
226 * Indexes created with NULLS NOT DISTINCT cannot be used for primary key
227 * constraints. While there is no direct syntax to reach here, it can be
228 * done by creating a separate index and attaching it via ALTER TABLE ..
229 * USING INDEX.
230 */
231 if (indexInfo->ii_NullsNotDistinct)
232 {
235 errmsg("primary keys cannot use NULLS NOT DISTINCT indexes")));
236 }
237
238 /*
239 * Check that all of the attributes in a primary key are marked as not
240 * null. (We don't really expect to see that; it'd mean the parser messed
241 * up. But it seems wise to check anyway.)
242 */
243 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
244 {
248
249 if (attnum == 0)
252 errmsg("primary keys cannot be expressions")));
253
254 /* System attributes are never null, so no need to check */
255 if (attnum < 0)
256 continue;
257
262 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
263 attnum, RelationGetRelid(heapRel));
265
266 if (!attform->attnotnull)
269 errmsg("primary key column \"%s\" is not marked NOT NULL",
270 NameStr(attform->attname))));
271
273 }
274}
275
276/*
277 * ConstructTupleDescriptor
278 *
279 * Build an index tuple descriptor for a new index
280 */
281static TupleDesc
283 const IndexInfo *indexInfo,
284 const List *indexColNames,
286 const Oid *collationIds,
287 const Oid *opclassIds)
288{
289 int numatts = indexInfo->ii_NumIndexAttrs;
290 int numkeyatts = indexInfo->ii_NumIndexKeyAttrs;
296 int natts; /* #atts in heap rel --- for error checks */
297 int i;
298
299 /* We need access to the index AM's API struct */
301
302 /* ... and to the table's tuple descriptor */
303 heapTupDesc = RelationGetDescr(heapRelation);
304 natts = RelationGetForm(heapRelation)->relnatts;
305
306 /*
307 * allocate the new tuple descriptor
308 */
310
311 /*
312 * Fill in the pg_attribute row.
313 */
314 for (i = 0; i < numatts; i++)
315 {
318 HeapTuple tuple;
321 Oid keyType;
322
324 to->attnum = i + 1;
325 to->attislocal = true;
326 to->attcollation = (i < numkeyatts) ? collationIds[i] : InvalidOid;
327
328 /*
329 * Set the attribute name as specified by caller.
330 */
331 if (colnames_item == NULL) /* shouldn't happen */
332 elog(ERROR, "too few entries in colnames list");
333 namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
335
336 /*
337 * For simple index columns, we copy some pg_attribute fields from the
338 * parent relation. For expressions we have to look at the expression
339 * result.
340 */
341 if (atnum != 0)
342 {
343 /* Simple index column */
344 const FormData_pg_attribute *from;
345
346 Assert(atnum > 0); /* should've been caught above */
347
348 if (atnum > natts) /* safety check */
349 elog(ERROR, "invalid column number %d", atnum);
352
353 to->atttypid = from->atttypid;
354 to->attlen = from->attlen;
355 to->attndims = from->attndims;
356 to->atttypmod = from->atttypmod;
357 to->attbyval = from->attbyval;
358 to->attalign = from->attalign;
359 to->attstorage = from->attstorage;
360 to->attcompression = from->attcompression;
361 }
362 else
363 {
364 /* Expressional index */
365 Node *indexkey;
366
367 if (indexpr_item == NULL) /* shouldn't happen */
368 elog(ERROR, "too few entries in indexprs list");
371
372 /*
373 * Lookup the expression type in pg_type for the type length etc.
374 */
377 if (!HeapTupleIsValid(tuple))
378 elog(ERROR, "cache lookup failed for type %u", keyType);
379 typeTup = (Form_pg_type) GETSTRUCT(tuple);
380
381 /*
382 * Assign some of the attributes values. Leave the rest.
383 */
384 to->atttypid = keyType;
385 to->attlen = typeTup->typlen;
386 to->atttypmod = exprTypmod(indexkey);
387 to->attbyval = typeTup->typbyval;
388 to->attalign = typeTup->typalign;
389 to->attstorage = typeTup->typstorage;
390
391 /*
392 * For expression columns, set attcompression invalid, since
393 * there's no table column from which to copy the value. Whenever
394 * we actually need to compress a value, we'll use whatever the
395 * current value of default_toast_compression is at that point in
396 * time.
397 */
398 to->attcompression = InvalidCompressionMethod;
399
400 ReleaseSysCache(tuple);
401
402 /*
403 * Make sure the expression yields a type that's safe to store in
404 * an index. We need this defense because we have index opclasses
405 * for pseudo-types such as "record", and the actually stored type
406 * had better be safe; eg, a named composite type is okay, an
407 * anonymous record type is not. The test is the same as for
408 * whether a table column is of a safe type (which is why we
409 * needn't check for the non-expression case).
410 */
411 CheckAttributeType(NameStr(to->attname),
412 to->atttypid, to->attcollation,
413 NIL, 0);
414 }
415
416 /*
417 * We do not yet have the correct relation OID for the index, so just
418 * set it invalid for now. InitializeAttributeOids() will fix it
419 * later.
420 */
421 to->attrelid = InvalidOid;
422
423 /*
424 * Check the opclass and index AM to see if either provides a keytype
425 * (overriding the attribute type). Opclass (if exists) takes
426 * precedence.
427 */
428 keyType = amroutine->amkeytype;
429
430 if (i < indexInfo->ii_NumIndexKeyAttrs)
431 {
433 if (!HeapTupleIsValid(tuple))
434 elog(ERROR, "cache lookup failed for opclass %u", opclassIds[i]);
436 if (OidIsValid(opclassTup->opckeytype))
437 keyType = opclassTup->opckeytype;
438
439 /*
440 * If keytype is specified as ANYELEMENT, and opcintype is
441 * ANYARRAY, then the attribute type must be an array (else it'd
442 * not have matched this opclass); use its element type.
443 *
444 * We could also allow ANYCOMPATIBLE/ANYCOMPATIBLEARRAY here, but
445 * there seems no need to do so; there's no reason to declare an
446 * opclass as taking ANYCOMPATIBLEARRAY rather than ANYARRAY.
447 */
448 if (keyType == ANYELEMENTOID && opclassTup->opcintype == ANYARRAYOID)
449 {
450 keyType = get_base_element_type(to->atttypid);
451 if (!OidIsValid(keyType))
452 elog(ERROR, "could not get element type of array type %u",
453 to->atttypid);
454 }
455
456 ReleaseSysCache(tuple);
457 }
458
459 /*
460 * If a key type different from the heap value is specified, update
461 * the type-related fields in the index tupdesc.
462 */
463 if (OidIsValid(keyType) && keyType != to->atttypid)
464 {
466 if (!HeapTupleIsValid(tuple))
467 elog(ERROR, "cache lookup failed for type %u", keyType);
468 typeTup = (Form_pg_type) GETSTRUCT(tuple);
469
470 to->atttypid = keyType;
471 to->atttypmod = -1;
472 to->attlen = typeTup->typlen;
473 to->attbyval = typeTup->typbyval;
474 to->attalign = typeTup->typalign;
475 to->attstorage = typeTup->typstorage;
476 /* As above, use the default compression method in this case */
477 to->attcompression = InvalidCompressionMethod;
478
479 ReleaseSysCache(tuple);
480 }
481
483 }
484
486
487 return indexTupDesc;
488}
489
490/* ----------------------------------------------------------------
491 * InitializeAttributeOids
492 * ----------------------------------------------------------------
493 */
494static void
496 int numatts,
497 Oid indexoid)
498{
500 int i;
501
502 tupleDescriptor = RelationGetDescr(indexRelation);
503
504 for (i = 0; i < numatts; i += 1)
505 TupleDescAttr(tupleDescriptor, i)->attrelid = indexoid;
506}
507
508/* ----------------------------------------------------------------
509 * AppendAttributeTuples
510 * ----------------------------------------------------------------
511 */
512static void
514{
519
520 if (attopts)
521 {
523
524 for (int i = 0; i < indexRelation->rd_att->natts; i++)
525 {
526 if (attopts[i])
527 attrs_extra[i].attoptions.value = attopts[i];
528 else
529 attrs_extra[i].attoptions.isnull = true;
530
531 if (stattargets)
532 attrs_extra[i].attstattarget = stattargets[i];
533 else
534 attrs_extra[i].attstattarget.isnull = true;
535 }
536 }
537
538 /*
539 * open the attribute relation and its indexes
540 */
542
544
545 /*
546 * insert data from new index's tupdesc into pg_attribute
547 */
548 indexTupDesc = RelationGetDescr(indexRelation);
549
551
553
555}
556
557/* ----------------------------------------------------------------
558 * UpdateIndexRelation
559 *
560 * Construct and insert a new entry in the pg_index catalog
561 * ----------------------------------------------------------------
562 */
563static void
565 Oid heapoid,
567 const IndexInfo *indexInfo,
568 const Oid *collationOids,
569 const Oid *opclassOids,
570 const int16 *coloptions,
571 bool primary,
572 bool isexclusion,
573 bool immediate,
574 bool isvalid,
575 bool isready)
576{
584 bool nulls[Natts_pg_index] = {0};
586 HeapTuple tuple;
587 int i;
588
589 /*
590 * Copy the index key, opclass, and indoption info into arrays (should we
591 * make the caller pass them like this to start with?)
592 */
594 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
595 indkey->values[i] = indexInfo->ii_IndexAttrNumbers[i];
599
600 /*
601 * Convert the index expressions (if any) to a text datum
602 */
603 if (indexInfo->ii_Expressions != NIL)
604 {
605 char *exprsString;
606
610 }
611 else
612 exprsDatum = (Datum) 0;
613
614 /*
615 * Convert the index predicate (if any) to a text datum. Note we convert
616 * implicit-AND format to normal explicit-AND for storage.
617 */
618 if (indexInfo->ii_Predicate != NIL)
619 {
620 char *predString;
621
625 }
626 else
627 predDatum = (Datum) 0;
628
629
630 /*
631 * open the system catalog index relation
632 */
634
635 /*
636 * Build a pg_index tuple
637 */
658 if (exprsDatum == (Datum) 0)
659 nulls[Anum_pg_index_indexprs - 1] = true;
661 if (predDatum == (Datum) 0)
662 nulls[Anum_pg_index_indpred - 1] = true;
663
665
666 /*
667 * insert the tuple into the pg_index catalog
668 */
670
671 /*
672 * close the relation and free the tuple
673 */
675 heap_freetuple(tuple);
676}
677
678
679/*
680 * index_create
681 *
682 * heapRelation: table to build index on (suitably locked by caller)
683 * indexRelationName: what it say
684 * indexRelationId: normally, pass InvalidOid to let this routine
685 * generate an OID for the index. During bootstrap this may be
686 * nonzero to specify a preselected OID.
687 * parentIndexRelid: if creating an index partition, the OID of the
688 * parent index; otherwise InvalidOid.
689 * parentConstraintId: if creating a constraint on a partition, the OID
690 * of the constraint in the parent; otherwise InvalidOid.
691 * relFileNumber: normally, pass InvalidRelFileNumber to get new storage.
692 * May be nonzero to attach an existing valid build.
693 * indexInfo: same info executor uses to insert into the index
694 * indexColNames: column names to use for index (List of char *)
695 * accessMethodId: OID of index AM to use
696 * tableSpaceId: OID of tablespace to use
697 * collationIds: array of collation OIDs, one per index column
698 * opclassIds: array of index opclass OIDs, one per index column
699 * coloptions: array of per-index-column indoption settings
700 * reloptions: AM-specific options
701 * flags: bitmask that can include any combination of these bits:
702 * INDEX_CREATE_IS_PRIMARY
703 * the index is a primary key
704 * INDEX_CREATE_ADD_CONSTRAINT:
705 * invoke index_constraint_create also
706 * INDEX_CREATE_SKIP_BUILD:
707 * skip the index_build() step for the moment; caller must do it
708 * later (typically via reindex_index())
709 * INDEX_CREATE_CONCURRENT:
710 * do not lock the table against writers. The index will be
711 * marked "invalid" and the caller must take additional steps
712 * to fix it up.
713 * INDEX_CREATE_IF_NOT_EXISTS:
714 * do not throw an error if a relation with the same name
715 * already exists.
716 * INDEX_CREATE_PARTITIONED:
717 * create a partitioned index (table must be partitioned)
718 * constr_flags: flags passed to index_constraint_create
719 * (only if INDEX_CREATE_ADD_CONSTRAINT is set)
720 * allow_system_table_mods: allow table to be a system catalog
721 * is_internal: if true, post creation hook for new index
722 * constraintId: if not NULL, receives OID of created constraint
723 *
724 * Returns the OID of the created index.
725 */
726Oid
728 const char *indexRelationName,
733 IndexInfo *indexInfo,
734 const List *indexColNames,
737 const Oid *collationIds,
738 const Oid *opclassIds,
739 const Datum *opclassOptions,
740 const int16 *coloptions,
742 Datum reloptions,
743 bits16 flags,
746 bool is_internal,
748{
749 Oid heapRelationId = RelationGetRelid(heapRelation);
751 Relation indexRelation;
753 bool shared_relation;
754 bool mapped_relation;
755 bool is_exclusion;
757 int i;
758 char relpersistence;
759 bool isprimary = (flags & INDEX_CREATE_IS_PRIMARY) != 0;
760 bool invalid = (flags & INDEX_CREATE_INVALID) != 0;
761 bool concurrent = (flags & INDEX_CREATE_CONCURRENT) != 0;
762 bool partitioned = (flags & INDEX_CREATE_PARTITIONED) != 0;
763 char relkind;
764 TransactionId relfrozenxid;
765 MultiXactId relminmxid;
767
768 /* constraint flags can only be set when a constraint is requested */
769 Assert((constr_flags == 0) ||
770 ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0));
771 /* partitioned indexes must never be "built" by themselves */
773
775 is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
776
778
779 /*
780 * The index will be in the same namespace as its parent table, and is
781 * shared across databases if and only if the parent is. Likewise, it
782 * will use the relfilenumber map if and only if the parent does; and it
783 * inherits the parent's relpersistence.
784 */
785 namespaceId = RelationGetNamespace(heapRelation);
786 shared_relation = heapRelation->rd_rel->relisshared;
787 mapped_relation = RelationIsMapped(heapRelation);
788 relpersistence = heapRelation->rd_rel->relpersistence;
789
790 /*
791 * check parameters
792 */
793 if (indexInfo->ii_NumIndexAttrs < 1)
794 elog(ERROR, "must index at least one column");
795
797 IsSystemRelation(heapRelation) &&
801 errmsg("user-defined indexes on system catalog tables are not supported")));
802
803 /*
804 * Btree text_pattern_ops uses texteq as the equality operator, which is
805 * fine as long as the collation is deterministic; texteq then reduces to
806 * bitwise equality and so it is semantically compatible with the other
807 * operators and functions in that opclass. But with a nondeterministic
808 * collation, texteq could yield results that are incompatible with the
809 * actual behavior of the index (which is determined by the opclass's
810 * comparison function). We prevent such problems by refusing creation of
811 * an index with that opclass and a nondeterministic collation.
812 *
813 * The same applies to varchar_pattern_ops and bpchar_pattern_ops. If we
814 * find more cases, we might decide to create a real mechanism for marking
815 * opclasses as incompatible with nondeterminism; but for now, this small
816 * hack suffices.
817 *
818 * Another solution is to use a special operator, not texteq, as the
819 * equality opclass member; but that is undesirable because it would
820 * prevent index usage in many queries that work fine today.
821 */
822 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
823 {
824 Oid collation = collationIds[i];
825 Oid opclass = opclassIds[i];
826
827 if (collation)
828 {
829 if ((opclass == TEXT_BTREE_PATTERN_OPS_OID ||
831 opclass == BPCHAR_BTREE_PATTERN_OPS_OID) &&
833 {
835
838 elog(ERROR, "cache lookup failed for operator class %u", opclass);
841 errmsg("nondeterministic collations are not supported for operator class \"%s\"",
844 }
845 }
846 }
847
848 /*
849 * Concurrent index build on a system catalog is unsafe because we tend to
850 * release locks before committing in catalogs.
851 */
852 if (concurrent &&
853 IsCatalogRelation(heapRelation))
856 errmsg("concurrent index creation on system catalog tables is not supported")));
857
858 /*
859 * This case is currently not supported. There's no way to ask for it in
860 * the grammar with CREATE INDEX, but it can happen with REINDEX.
861 */
862 if (concurrent && is_exclusion)
865 errmsg("concurrent index creation for exclusion constraints is not supported")));
866
867 /*
868 * We cannot allow indexing a shared relation after initdb (because
869 * there's no way to make the entry in other databases' pg_class).
870 */
874 errmsg("shared indexes cannot be created after initdb")));
875
876 /*
877 * Shared relations must be in pg_global, too (last-ditch check)
878 */
880 elog(ERROR, "shared relations must be placed in pg_global tablespace");
881
882 /*
883 * Check for duplicate name (both as to the index, and as to the
884 * associated constraint if any). Such cases would fail on the relevant
885 * catalogs' unique indexes anyway, but we prefer to give a friendlier
886 * error message.
887 */
889 {
890 if ((flags & INDEX_CREATE_IF_NOT_EXISTS) != 0)
891 {
894 errmsg("relation \"%s\" already exists, skipping",
897 return InvalidOid;
898 }
899
902 errmsg("relation \"%s\" already exists",
904 }
905
906 if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0 &&
909 {
910 /*
911 * INDEX_CREATE_IF_NOT_EXISTS does not apply here, since the
912 * conflicting constraint is not an index.
913 */
916 errmsg("constraint \"%s\" for relation \"%s\" already exists",
918 }
919
920 /*
921 * construct tuple descriptor for index tuples
922 */
924 indexInfo,
928 opclassIds);
929
930 /*
931 * Allocate an OID for the index, unless we were told what to use.
932 *
933 * The OID will be the relfilenumber as well, so make sure it doesn't
934 * collide with either pg_class OIDs or existing physical files.
935 */
937 {
938 /* Use binary-upgrade override for pg_class.oid and relfilenumber */
939 if (IsBinaryUpgrade)
940 {
944 errmsg("pg_class index OID value not set when in binary upgrade mode")));
945
948
949 /* Override the index relfilenumber */
950 if ((relkind == RELKIND_INDEX) &&
954 errmsg("index relfilenumber value not set when in binary upgrade mode")));
957
958 /*
959 * Note that we want create_storage = true for binary upgrade. The
960 * storage we create here will be replaced later, but we need to
961 * have something on disk in the meanwhile.
962 */
964 }
965 else
966 {
968 GetNewRelFileNumber(tableSpaceId, pg_class, relpersistence);
969 }
970 }
971
972 /*
973 * create the index relation's relcache entry and, if necessary, the
974 * physical disk file. (If we fail further down, it's the smgr's
975 * responsibility to remove the disk file again, if any.)
976 */
977 indexRelation = heap_create(indexRelationName,
984 relkind,
985 relpersistence,
989 &relfrozenxid,
990 &relminmxid,
992
993 Assert(relfrozenxid == InvalidTransactionId);
994 Assert(relminmxid == InvalidMultiXactId);
995 Assert(indexRelationId == RelationGetRelid(indexRelation));
996
997 /*
998 * Obtain exclusive lock on it. Although no other transactions can see it
999 * until we commit, this prevents deadlock-risk complaints from lock
1000 * manager in cases such as CLUSTER.
1001 */
1002 LockRelation(indexRelation, AccessExclusiveLock);
1003
1004 /*
1005 * Fill in fields of the index's pg_class entry that are not set correctly
1006 * by heap_create.
1007 *
1008 * XXX should have a cleaner way to create cataloged indexes
1009 */
1010 indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
1011 indexRelation->rd_rel->relam = accessMethodId;
1012 indexRelation->rd_rel->relispartition = OidIsValid(parentIndexRelid);
1013
1014 /*
1015 * store index's pg_class entry
1016 */
1017 InsertPgClassTuple(pg_class, indexRelation,
1018 RelationGetRelid(indexRelation),
1019 (Datum) 0,
1020 reloptions);
1021
1022 /* done with pg_class */
1024
1025 /*
1026 * now update the object id's of all the attribute tuple forms in the
1027 * index relation's tuple descriptor
1028 */
1029 InitializeAttributeOids(indexRelation,
1030 indexInfo->ii_NumIndexAttrs,
1032
1033 /*
1034 * append ATTRIBUTE tuples for the index
1035 */
1037
1038 /* ----------------
1039 * update pg_index
1040 * (append INDEX tuple)
1041 *
1042 * Note that this stows away a representation of "predicate".
1043 * (Or, could define a rule to maintain the predicate) --Nels, Feb '92
1044 * ----------------
1045 */
1047 indexInfo,
1051 !concurrent && !invalid,
1052 !concurrent);
1053
1054 /*
1055 * Register relcache invalidation on the indexes' heap relation, to
1056 * maintain consistency of its index list
1057 */
1058 CacheInvalidateRelcache(heapRelation);
1059
1060 /* update pg_inherits and the parent's relhassubclass, if needed */
1062 {
1066 }
1067
1068 /*
1069 * Register constraint and dependencies for the index.
1070 *
1071 * If the index is from a CONSTRAINT clause, construct a pg_constraint
1072 * entry. The index will be linked to the constraint, which in turn is
1073 * linked to the table. If it's not a CONSTRAINT, we need to make a
1074 * dependency directly on the table.
1075 *
1076 * We don't need a dependency on the namespace, because there'll be an
1077 * indirect dependency via our parent table.
1078 *
1079 * During bootstrap we can't register any dependencies, and we don't try
1080 * to make a constraint either.
1081 */
1083 {
1085 referenced;
1086 ObjectAddresses *addrs;
1087
1089
1090 if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0)
1091 {
1092 char constraintType;
1094
1095 if (isprimary)
1097 else if (indexInfo->ii_Unique)
1099 else if (is_exclusion)
1101 else
1102 {
1103 elog(ERROR, "constraint must be PRIMARY, UNIQUE or EXCLUDE");
1104 constraintType = 0; /* keep compiler quiet */
1105 }
1106
1107 localaddr = index_constraint_create(heapRelation,
1110 indexInfo,
1115 is_internal);
1116 if (constraintId)
1117 *constraintId = localaddr.objectId;
1118 }
1119 else
1120 {
1121 bool have_simple_col = false;
1122
1123 addrs = new_object_addresses();
1124
1125 /* Create auto dependencies on simply-referenced columns */
1126 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1127 {
1128 if (indexInfo->ii_IndexAttrNumbers[i] != 0)
1129 {
1132 indexInfo->ii_IndexAttrNumbers[i]);
1134 have_simple_col = true;
1135 }
1136 }
1137
1138 /*
1139 * If there are no simply-referenced columns, give the index an
1140 * auto dependency on the whole table. In most cases, this will
1141 * be redundant, but it might not be if the index expressions and
1142 * predicate contain no Vars or only whole-row Vars.
1143 */
1144 if (!have_simple_col)
1145 {
1149 }
1150
1152 free_object_addresses(addrs);
1153 }
1154
1155 /*
1156 * If this is an index partition, create partition dependencies on
1157 * both the parent index and the table. (Note: these must be *in
1158 * addition to*, not instead of, all other dependencies. Otherwise
1159 * we'll be short some dependencies after DETACH PARTITION.)
1160 */
1162 {
1165
1168 }
1169
1170 /* placeholder for normal dependencies */
1171 addrs = new_object_addresses();
1172
1173 /* Store dependency on collations */
1174
1175 /* The default collation is pinned, so don't bother recording it */
1176 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1177 {
1179 {
1182 }
1183 }
1184
1185 /* Store dependency on operator classes */
1186 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1187 {
1190 }
1191
1193 free_object_addresses(addrs);
1194
1195 /* Store dependencies on anything mentioned in index expressions */
1196 if (indexInfo->ii_Expressions)
1197 {
1199 (Node *) indexInfo->ii_Expressions,
1202 DEPENDENCY_AUTO, false);
1203 }
1204
1205 /* Store dependencies on anything mentioned in predicate */
1206 if (indexInfo->ii_Predicate)
1207 {
1209 (Node *) indexInfo->ii_Predicate,
1212 DEPENDENCY_AUTO, false);
1213 }
1214 }
1215 else
1216 {
1217 /* Bootstrap mode - assert we weren't asked for constraint support */
1218 Assert((flags & INDEX_CREATE_ADD_CONSTRAINT) == 0);
1219 }
1220
1221 /* Post creation hook for new index */
1223 indexRelationId, 0, is_internal);
1224
1225 /*
1226 * Advance the command counter so that we can see the newly-entered
1227 * catalog tuples for the index.
1228 */
1230
1231 /*
1232 * In bootstrap mode, we have to fill in the index strategy structure with
1233 * information from the catalogs. If we aren't bootstrapping, then the
1234 * relcache entry has already been rebuilt thanks to sinval update during
1235 * CommandCounterIncrement.
1236 */
1238 RelationInitIndexAccessInfo(indexRelation);
1239 else
1240 Assert(indexRelation->rd_indexcxt != NULL);
1241
1242 indexRelation->rd_index->indnkeyatts = indexInfo->ii_NumIndexKeyAttrs;
1243
1244 /* Validate opclass-specific options */
1245 if (opclassOptions)
1246 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1247 (void) index_opclass_options(indexRelation, i + 1,
1249 true);
1250
1251 /*
1252 * If this is bootstrap (initdb) time, then we don't actually fill in the
1253 * index yet. We'll be creating more indexes and classes later, so we
1254 * delay filling them in until just before we're done with bootstrapping.
1255 * Similarly, if the caller specified to skip the build then filling the
1256 * index is delayed till later (ALTER TABLE can save work in some cases
1257 * with this). Otherwise, we call the AM routine that constructs the
1258 * index.
1259 */
1261 {
1263 }
1264 else if ((flags & INDEX_CREATE_SKIP_BUILD) != 0)
1265 {
1266 /*
1267 * Caller is responsible for filling the index later on. However,
1268 * we'd better make sure that the heap relation is correctly marked as
1269 * having an index.
1270 */
1271 index_update_stats(heapRelation,
1272 true,
1273 -1.0);
1274 /* Make the above update visible */
1276 }
1277 else
1278 {
1279 index_build(heapRelation, indexRelation, indexInfo, false, true);
1280 }
1281
1282 /*
1283 * Close the index; but we keep the lock that we acquired above until end
1284 * of transaction. Closing the heap is caller's responsibility.
1285 */
1286 index_close(indexRelation, NoLock);
1287
1288 return indexRelationId;
1289}
1290
1291/*
1292 * index_concurrently_create_copy
1293 *
1294 * Create concurrently an index based on the definition of the one provided by
1295 * caller. The index is inserted into catalogs and needs to be built later
1296 * on. This is called during concurrent reindex processing.
1297 *
1298 * "tablespaceOid" is the tablespace to use for this index.
1299 */
1300Oid
1302 Oid tablespaceOid, const char *newName)
1303{
1304 Relation indexRelation;
1306 *newInfo;
1309 classTuple;
1317 bool isnull;
1319 List *indexExprs = NIL;
1320 List *indexPreds = NIL;
1321
1322 indexRelation = index_open(oldIndexId, RowExclusiveLock);
1323
1324 /* The new index needs some information from the old index */
1325 oldInfo = BuildIndexInfo(indexRelation);
1326
1327 /*
1328 * Concurrent build of an index with exclusion constraints is not
1329 * supported.
1330 */
1331 if (oldInfo->ii_ExclusionOps != NULL)
1332 ereport(ERROR,
1334 errmsg("concurrent index creation for exclusion constraints is not supported")));
1335
1336 /* Get the array of class and column options IDs from index info */
1339 elog(ERROR, "cache lookup failed for index %u", oldIndexId);
1343
1347
1348 /* Fetch reloptions of index if any */
1351 elog(ERROR, "cache lookup failed for relation %u", oldIndexId);
1353 Anum_pg_class_reloptions, &isnull);
1354
1355 /*
1356 * Fetch the list of expressions and predicates directly from the
1357 * catalogs. This cannot rely on the information from IndexInfo of the
1358 * old index as these have been flattened for the planner.
1359 */
1360 if (oldInfo->ii_Expressions != NIL)
1361 {
1363 char *exprString;
1364
1370 }
1371 if (oldInfo->ii_Predicate != NIL)
1372 {
1374 char *predString;
1375
1380
1381 /* Also convert to implicit-AND format */
1384 }
1385
1386 /*
1387 * Build the index information for the new index. Note that rebuild of
1388 * indexes with exclusion constraints is not supported, hence there is no
1389 * need to fill all the ii_Exclusion* fields.
1390 */
1391 newInfo = makeIndexInfo(oldInfo->ii_NumIndexAttrs,
1392 oldInfo->ii_NumIndexKeyAttrs,
1393 oldInfo->ii_Am,
1394 indexExprs,
1395 indexPreds,
1396 oldInfo->ii_Unique,
1397 oldInfo->ii_NullsNotDistinct,
1398 false, /* not ready for inserts */
1399 true,
1400 indexRelation->rd_indam->amsummarizing,
1401 oldInfo->ii_WithoutOverlaps);
1402
1403 /*
1404 * Extract the list of column names and the column numbers for the new
1405 * index information. All this information will be used for the index
1406 * creation.
1407 */
1408 for (int i = 0; i < oldInfo->ii_NumIndexAttrs; i++)
1409 {
1410 TupleDesc indexTupDesc = RelationGetDescr(indexRelation);
1412
1414 newInfo->ii_IndexAttrNumbers[i] = oldInfo->ii_IndexAttrNumbers[i];
1415 }
1416
1417 /* Extract opclass options for each attribute */
1418 opclassOptions = palloc0_array(Datum, newInfo->ii_NumIndexAttrs);
1419 for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
1421
1422 /* Extract statistic targets for each attribute */
1423 stattargets = palloc0_array(NullableDatum, newInfo->ii_NumIndexAttrs);
1424 for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
1425 {
1426 HeapTuple tp;
1427 Datum dat;
1428
1430 if (!HeapTupleIsValid(tp))
1431 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1432 i + 1, oldIndexId);
1434 ReleaseSysCache(tp);
1435 stattargets[i].value = dat;
1436 stattargets[i].isnull = isnull;
1437 }
1438
1439 /*
1440 * Now create the new index.
1441 *
1442 * For a partition index, we adjust the partition dependency later, to
1443 * ensure a consistent state at all times. That is why parentIndexRelid
1444 * is not set here.
1445 */
1446 newIndexId = index_create(heapRelation,
1447 newName,
1448 InvalidOid, /* indexRelationId */
1449 InvalidOid, /* parentIndexRelid */
1450 InvalidOid, /* parentConstraintId */
1451 InvalidRelFileNumber, /* relFileNumber */
1452 newInfo,
1454 indexRelation->rd_rel->relam,
1455 tablespaceOid,
1456 indexRelation->rd_indcollation,
1457 indclass->values,
1459 indcoloptions->values,
1463 0,
1464 true, /* allow table to be a system catalog? */
1465 false, /* is_internal? */
1466 NULL);
1467
1468 /* Close the relations used and clean up */
1469 index_close(indexRelation, NoLock);
1472
1473 return newIndexId;
1474}
1475
1476/*
1477 * index_concurrently_build
1478 *
1479 * Build index for a concurrent operation. Low-level locks are taken when
1480 * this operation is performed to prevent only schema changes, but they need
1481 * to be kept until the end of the transaction performing this operation.
1482 * 'indexOid' refers to an index relation OID already created as part of
1483 * previous processing, and 'heapOid' refers to its parent heap relation.
1484 */
1485void
1488{
1489 Relation heapRel;
1490 Oid save_userid;
1491 int save_sec_context;
1492 int save_nestlevel;
1493 Relation indexRelation;
1494 IndexInfo *indexInfo;
1495
1496 /* This had better make sure that a snapshot is active */
1498
1499 /* Open and lock the parent heap relation */
1501
1502 /*
1503 * Switch to the table owner's userid, so that any index functions are run
1504 * as that user. Also lock down security-restricted operations and
1505 * arrange to make GUC variable changes local to this command.
1506 */
1507 GetUserIdAndSecContext(&save_userid, &save_sec_context);
1508 SetUserIdAndSecContext(heapRel->rd_rel->relowner,
1509 save_sec_context | SECURITY_RESTRICTED_OPERATION);
1510 save_nestlevel = NewGUCNestLevel();
1512
1514
1515 /*
1516 * We have to re-build the IndexInfo struct, since it was lost in the
1517 * commit of the transaction where this concurrent index was created at
1518 * the catalog level.
1519 */
1520 indexInfo = BuildIndexInfo(indexRelation);
1521 Assert(!indexInfo->ii_ReadyForInserts);
1522 indexInfo->ii_Concurrent = true;
1523 indexInfo->ii_BrokenHotChain = false;
1524
1525 /* Now build the index */
1526 index_build(heapRel, indexRelation, indexInfo, false, true);
1527
1528 /* Roll back any GUC changes executed by index functions */
1529 AtEOXact_GUC(false, save_nestlevel);
1530
1531 /* Restore userid and security context */
1532 SetUserIdAndSecContext(save_userid, save_sec_context);
1533
1534 /* Close both the relations, but keep the locks */
1535 table_close(heapRel, NoLock);
1536 index_close(indexRelation, NoLock);
1537
1538 /*
1539 * Update the pg_index row to mark the index as ready for inserts. Once we
1540 * commit this transaction, any new transactions that open the table must
1541 * insert new entries into the index for insertions and non-HOT updates.
1542 */
1544}
1545
1546/*
1547 * index_concurrently_swap
1548 *
1549 * Swap name, dependencies, and constraints of the old index over to the new
1550 * index, while marking the old index as invalid and the new as valid.
1551 */
1552void
1554{
1556 pg_index,
1558 pg_trigger;
1569 bool isPartition;
1572 ListCell *lc;
1573
1574 /*
1575 * Take a necessary lock on the old and new index before swapping them.
1576 */
1579
1580 /* Now swap names and dependencies of those indexes */
1582
1586 elog(ERROR, "could not find tuple for relation %u", oldIndexId);
1590 elog(ERROR, "could not find tuple for relation %u", newIndexId);
1591
1594
1595 /* Swap the names */
1596 namestrcpy(&newClassForm->relname, NameStr(oldClassForm->relname));
1597 namestrcpy(&oldClassForm->relname, oldName);
1598
1599 /* Swap the partition flags to track inheritance properly */
1600 isPartition = newClassForm->relispartition;
1601 newClassForm->relispartition = oldClassForm->relispartition;
1602 oldClassForm->relispartition = isPartition;
1603
1606
1609
1610 /* Now swap index info */
1612
1616 elog(ERROR, "could not find tuple for relation %u", oldIndexId);
1620 elog(ERROR, "could not find tuple for relation %u", newIndexId);
1621
1624
1625 /*
1626 * Copy constraint flags from the old index. This is safe because the old
1627 * index guaranteed uniqueness.
1628 */
1629 newIndexForm->indisprimary = oldIndexForm->indisprimary;
1630 oldIndexForm->indisprimary = false;
1631 newIndexForm->indisexclusion = oldIndexForm->indisexclusion;
1632 oldIndexForm->indisexclusion = false;
1633 newIndexForm->indimmediate = oldIndexForm->indimmediate;
1634 oldIndexForm->indimmediate = true;
1635
1636 /* Preserve indisreplident in the new index */
1637 newIndexForm->indisreplident = oldIndexForm->indisreplident;
1638
1639 /* Preserve indisclustered in the new index */
1640 newIndexForm->indisclustered = oldIndexForm->indisclustered;
1641
1642 /*
1643 * Mark the new index as valid, and the old index as invalid similarly to
1644 * what index_set_state_flags() does.
1645 */
1646 newIndexForm->indisvalid = true;
1647 oldIndexForm->indisvalid = false;
1648 oldIndexForm->indisclustered = false;
1649 oldIndexForm->indisreplident = false;
1650
1653
1656
1657 /*
1658 * Move constraints and triggers over to the new index
1659 */
1660
1662
1664
1667
1670
1671 foreach(lc, constraintOids)
1672 {
1676 ScanKeyData key[1];
1677 SysScanDesc scan;
1679
1680 /* Move the constraint from the old to the new index */
1684 elog(ERROR, "could not find tuple for constraint %u", constraintOid);
1685
1687
1688 if (conForm->conindid == oldIndexId)
1689 {
1690 conForm->conindid = newIndexId;
1691
1693 }
1694
1696
1697 /* Search for trigger records */
1698 ScanKeyInit(&key[0],
1702
1704 NULL, 1, key);
1705
1707 {
1709
1710 if (tgForm->tgconstrindid != oldIndexId)
1711 continue;
1712
1713 /* Make a modifiable copy */
1716
1717 tgForm->tgconstrindid = newIndexId;
1718
1720
1722 }
1723
1724 systable_endscan(scan);
1725 }
1726
1727 /*
1728 * Move comment if any
1729 */
1730 {
1732 ScanKeyData skey[3];
1734 HeapTuple tuple;
1736 bool nulls[Natts_pg_description] = {0};
1737 bool replaces[Natts_pg_description] = {0};
1738
1741
1742 ScanKeyInit(&skey[0],
1746 ScanKeyInit(&skey[1],
1750 ScanKeyInit(&skey[2],
1753 Int32GetDatum(0));
1754
1756
1758 NULL, 3, skey);
1759
1760 while ((tuple = systable_getnext(sd)) != NULL)
1761 {
1763 values, nulls, replaces);
1764 CatalogTupleUpdate(description, &tuple->t_self, tuple);
1765
1766 break; /* Assume there can be only one match */
1767 }
1768
1771 }
1772
1773 /*
1774 * Swap inheritance relationship with parent index
1775 */
1777 {
1779 Oid parentIndexRelid = linitial_oid(ancestors);
1780
1783
1784 list_free(ancestors);
1785 }
1786
1787 /*
1788 * Swap all dependencies of and on the old index to the new one, and
1789 * vice-versa. Note that a call to CommandCounterIncrement() would cause
1790 * duplicate entries in pg_depend, so this should not be done.
1791 */
1794
1797
1798 /* copy over statistics from old to new index */
1800
1801 /* Copy data of pg_statistic from the old index to the new one */
1803
1804 /* Close relations */
1809
1810 /* The lock taken previously is not released until the end of transaction */
1813}
1814
1815/*
1816 * index_concurrently_set_dead
1817 *
1818 * Perform the last invalidation stage of DROP INDEX CONCURRENTLY or REINDEX
1819 * CONCURRENTLY before actually dropping the index. After calling this
1820 * function, the index is seen by all the backends as dead. Low-level locks
1821 * taken here are kept until the end of the transaction calling this function.
1822 */
1823void
1825{
1828
1829 /*
1830 * No more predicate locks will be acquired on this index, and we're about
1831 * to stop doing inserts into the index which could show conflicts with
1832 * existing predicate locks, so now is the time to move them to the heap
1833 * relation.
1834 */
1838
1839 /*
1840 * Now we are sure that nobody uses the index for queries; they just might
1841 * have it open for updating it. So now we can unset indisready and
1842 * indislive, then wait till nobody could be using it at all anymore.
1843 */
1845
1846 /*
1847 * Invalidate the relcache for the table, so that after this commit all
1848 * sessions will refresh the table's index list. Forgetting just the
1849 * index's relcache entry is not enough.
1850 */
1852
1853 /*
1854 * Close the relations again, though still holding session lock.
1855 */
1858}
1859
1860/*
1861 * index_constraint_create
1862 *
1863 * Set up a constraint associated with an index. Return the new constraint's
1864 * address.
1865 *
1866 * heapRelation: table owning the index (must be suitably locked by caller)
1867 * indexRelationId: OID of the index
1868 * parentConstraintId: if constraint is on a partition, the OID of the
1869 * constraint in the parent.
1870 * indexInfo: same info executor uses to insert into the index
1871 * constraintName: what it say (generally, should match name of index)
1872 * constraintType: one of CONSTRAINT_PRIMARY, CONSTRAINT_UNIQUE, or
1873 * CONSTRAINT_EXCLUSION
1874 * flags: bitmask that can include any combination of these bits:
1875 * INDEX_CONSTR_CREATE_MARK_AS_PRIMARY: index is a PRIMARY KEY
1876 * INDEX_CONSTR_CREATE_DEFERRABLE: constraint is DEFERRABLE
1877 * INDEX_CONSTR_CREATE_INIT_DEFERRED: constraint is INITIALLY DEFERRED
1878 * INDEX_CONSTR_CREATE_UPDATE_INDEX: update the pg_index row
1879 * INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS: remove existing dependencies
1880 * of index on table's columns
1881 * INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS: constraint uses WITHOUT OVERLAPS
1882 * allow_system_table_mods: allow table to be a system catalog
1883 * is_internal: index is constructed due to internal process
1884 */
1889 const IndexInfo *indexInfo,
1890 const char *constraintName,
1891 char constraintType,
1894 bool is_internal)
1895{
1896 Oid namespaceId = RelationGetNamespace(heapRelation);
1898 idxaddr;
1899 Oid conOid;
1900 bool deferrable;
1901 bool initdeferred;
1902 bool mark_as_primary;
1903 bool islocal;
1904 bool noinherit;
1906 int16 inhcount;
1907
1908 deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
1909 initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;
1912
1913 /* constraint creation support doesn't work while bootstrapping */
1915
1916 /* enforce system-table restriction */
1918 IsSystemRelation(heapRelation) &&
1920 ereport(ERROR,
1922 errmsg("user-defined indexes on system catalog tables are not supported")));
1923
1924 /* primary/unique constraints shouldn't have any expressions */
1925 if (indexInfo->ii_Expressions &&
1927 elog(ERROR, "constraints cannot have index expressions");
1928
1929 /*
1930 * If we're manufacturing a constraint for a pre-existing index, we need
1931 * to get rid of the existing auto dependencies for the index (the ones
1932 * that index_create() would have made instead of calling this function).
1933 *
1934 * Note: this code would not necessarily do the right thing if the index
1935 * has any expressions or predicate, but we'd never be turning such an
1936 * index into a UNIQUE or PRIMARY KEY constraint.
1937 */
1941
1943 {
1944 islocal = false;
1945 inhcount = 1;
1946 noinherit = false;
1947 }
1948 else
1949 {
1950 islocal = true;
1951 inhcount = 0;
1952 noinherit = true;
1953 }
1954
1955 /*
1956 * Construct a pg_constraint entry.
1957 */
1961 deferrable,
1962 initdeferred,
1963 true, /* Is Enforced */
1964 true,
1966 RelationGetRelid(heapRelation),
1967 indexInfo->ii_IndexAttrNumbers,
1968 indexInfo->ii_NumIndexKeyAttrs,
1969 indexInfo->ii_NumIndexAttrs,
1970 InvalidOid, /* no domain */
1971 indexRelationId, /* index OID */
1972 InvalidOid, /* no foreign key */
1973 NULL,
1974 NULL,
1975 NULL,
1976 NULL,
1977 0,
1978 ' ',
1979 ' ',
1980 NULL,
1981 0,
1982 ' ',
1983 indexInfo->ii_ExclusionOps,
1984 NULL, /* no check constraint */
1985 NULL,
1986 islocal,
1987 inhcount,
1988 noinherit,
1990 is_internal);
1991
1992 /*
1993 * Register the index as internally dependent on the constraint.
1994 *
1995 * Note that the constraint has a dependency on the table, so we don't
1996 * need (or want) any direct dependency from the index to the table.
1997 */
2001
2002 /*
2003 * Also, if this is a constraint on a partition, give it partition-type
2004 * dependencies on the parent constraint as well as the table.
2005 */
2007 {
2009
2013 RelationGetRelid(heapRelation));
2015 }
2016
2017 /*
2018 * If the constraint is deferrable, create the deferred uniqueness
2019 * checking trigger. (The trigger will be given an internal dependency on
2020 * the constraint by CreateTrigger.)
2021 */
2022 if (deferrable)
2023 {
2025
2026 trigger->replace = false;
2027 trigger->isconstraint = true;
2028 trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ?
2029 "PK_ConstraintTrigger" :
2030 "Unique_ConstraintTrigger";
2031 trigger->relation = NULL;
2032 trigger->funcname = SystemFuncName("unique_key_recheck");
2033 trigger->args = NIL;
2034 trigger->row = true;
2035 trigger->timing = TRIGGER_TYPE_AFTER;
2037 trigger->columns = NIL;
2038 trigger->whenClause = NULL;
2039 trigger->transitionRels = NIL;
2040 trigger->deferrable = true;
2041 trigger->initdeferred = initdeferred;
2042 trigger->constrrel = NULL;
2043
2046 InvalidOid, NULL, true, false);
2047 }
2048
2049 /*
2050 * If needed, mark the index as primary and/or deferred in pg_index.
2051 *
2052 * Note: When making an existing index into a constraint, caller must have
2053 * a table lock that prevents concurrent table updates; otherwise, there
2054 * is a risk that concurrent readers of the table will miss seeing this
2055 * index at all.
2056 */
2058 (mark_as_primary || deferrable))
2059 {
2063 bool dirty = false;
2064 bool marked_as_primary = false;
2065
2067
2071 elog(ERROR, "cache lookup failed for index %u", indexRelationId);
2073
2074 if (mark_as_primary && !indexForm->indisprimary)
2075 {
2076 indexForm->indisprimary = true;
2077 dirty = true;
2078 marked_as_primary = true;
2079 }
2080
2081 if (deferrable && indexForm->indimmediate)
2082 {
2083 indexForm->indimmediate = false;
2084 dirty = true;
2085 }
2086
2087 if (dirty)
2088 {
2090
2091 /*
2092 * When we mark an existing index as primary, force a relcache
2093 * flush on its parent table, so that all sessions will become
2094 * aware that the table now has a primary key. This is important
2095 * because it affects some replication behaviors.
2096 */
2098 CacheInvalidateRelcache(heapRelation);
2099
2101 InvalidOid, is_internal);
2102 }
2103
2106 }
2107
2108 return myself;
2109}
2110
2111/*
2112 * index_drop
2113 *
2114 * NOTE: this routine should now only be called through performDeletion(),
2115 * else associated dependencies won't be cleaned up.
2116 *
2117 * If concurrent is true, do a DROP INDEX CONCURRENTLY. If concurrent is
2118 * false but concurrent_lock_mode is true, then do a normal DROP INDEX but
2119 * take a lock for CONCURRENTLY processing. That is used as part of REINDEX
2120 * CONCURRENTLY.
2121 */
2122void
2124{
2125 Oid heapId;
2128 Relation indexRelation;
2129 HeapTuple tuple;
2130 bool hasexprs;
2131 LockRelId heaprelid,
2132 indexrelid;
2134 LOCKMODE lockmode;
2135
2136 /*
2137 * A temporary relation uses a non-concurrent DROP. Other backends can't
2138 * access a temporary relation, so there's no harm in grabbing a stronger
2139 * lock (see comments in RemoveRelations), and a non-concurrent DROP is
2140 * more efficient.
2141 */
2143 (!concurrent && !concurrent_lock_mode));
2144
2145 /*
2146 * To drop an index safely, we must grab exclusive lock on its parent
2147 * table. Exclusive lock on the index alone is insufficient because
2148 * another backend might be about to execute a query on the parent table.
2149 * If it relies on a previously cached list of index OIDs, then it could
2150 * attempt to access the just-dropped index. We must therefore take a
2151 * table lock strong enough to prevent all queries on the table from
2152 * proceeding until we commit and send out a shared-cache-inval notice
2153 * that will make them update their index lists.
2154 *
2155 * In the concurrent case we avoid this requirement by disabling index use
2156 * in multiple steps and waiting out any transactions that might be using
2157 * the index, so we don't need exclusive lock on the parent table. Instead
2158 * we take ShareUpdateExclusiveLock, to ensure that two sessions aren't
2159 * doing CREATE/DROP INDEX CONCURRENTLY on the same index. (We will get
2160 * AccessExclusiveLock on the index below, once we're sure nobody else is
2161 * using it.)
2162 */
2165 userHeapRelation = table_open(heapId, lockmode);
2167
2168 /*
2169 * We might still have open queries using it in our own session, which the
2170 * above locking won't prevent, so test explicitly.
2171 */
2173
2174 /*
2175 * Drop Index Concurrently is more or less the reverse process of Create
2176 * Index Concurrently.
2177 *
2178 * First we unset indisvalid so queries starting afterwards don't use the
2179 * index to answer queries anymore. We have to keep indisready = true so
2180 * transactions that are still scanning the index can continue to see
2181 * valid index contents. For instance, if they are using READ COMMITTED
2182 * mode, and another transaction makes changes and commits, they need to
2183 * see those new tuples in the index.
2184 *
2185 * After all transactions that could possibly have used the index for
2186 * queries end, we can unset indisready and indislive, then wait till
2187 * nobody could be touching it anymore. (Note: we need indislive because
2188 * this state must be distinct from the initial state during CREATE INDEX
2189 * CONCURRENTLY, which has indislive true while indisready and indisvalid
2190 * are false. That's because in that state, transactions must examine the
2191 * index for HOT-safety decisions, while in this state we don't want them
2192 * to open it at all.)
2193 *
2194 * Since all predicate locks on the index are about to be made invalid, we
2195 * must promote them to predicate locks on the heap. In the
2196 * non-concurrent case we can just do that now. In the concurrent case
2197 * it's a bit trickier. The predicate locks must be moved when there are
2198 * no index scans in progress on the index and no more can subsequently
2199 * start, so that no new predicate locks can be made on the index. Also,
2200 * they must be moved before heap inserts stop maintaining the index, else
2201 * the conflict with the predicate lock on the index gap could be missed
2202 * before the lock on the heap relation is in place to detect a conflict
2203 * based on the heap tuple insert.
2204 */
2205 if (concurrent)
2206 {
2207 /*
2208 * We must commit our transaction in order to make the first pg_index
2209 * state update visible to other sessions. If the DROP machinery has
2210 * already performed any other actions (removal of other objects,
2211 * pg_depend entries, etc), the commit would make those actions
2212 * permanent, which would leave us with inconsistent catalog state if
2213 * we fail partway through the following sequence. Since DROP INDEX
2214 * CONCURRENTLY is restricted to dropping just one index that has no
2215 * dependencies, we should get here before anything's been done ---
2216 * but let's check that to be sure. We can verify that the current
2217 * transaction has not executed any transactional updates by checking
2218 * that no XID has been assigned.
2219 */
2221 ereport(ERROR,
2223 errmsg("DROP INDEX CONCURRENTLY must be first action in transaction")));
2224
2225 /*
2226 * Mark index invalid by updating its pg_index entry
2227 */
2229
2230 /*
2231 * Invalidate the relcache for the table, so that after this commit
2232 * all sessions will refresh any cached plans that might reference the
2233 * index.
2234 */
2236
2237 /* save lockrelid and locktag for below, then close but keep locks */
2238 heaprelid = userHeapRelation->rd_lockInfo.lockRelId;
2239 SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
2240 indexrelid = userIndexRelation->rd_lockInfo.lockRelId;
2241
2244
2245 /*
2246 * We must commit our current transaction so that the indisvalid
2247 * update becomes visible to other transactions; then start another.
2248 * Note that any previously-built data structures are lost in the
2249 * commit. The only data we keep past here are the relation IDs.
2250 *
2251 * Before committing, get a session-level lock on the table, to ensure
2252 * that neither it nor the index can be dropped before we finish. This
2253 * cannot block, even if someone else is waiting for access, because
2254 * we already have the same lock within our transaction.
2255 */
2258
2262
2263 /*
2264 * Now we must wait until no running transaction could be using the
2265 * index for a query. Use AccessExclusiveLock here to check for
2266 * running transactions that hold locks of any kind on the table. Note
2267 * we do not need to worry about xacts that open the table for reading
2268 * after this point; they will see the index as invalid when they open
2269 * the relation.
2270 *
2271 * Note: the reason we use actual lock acquisition here, rather than
2272 * just checking the ProcArray and sleeping, is that deadlock is
2273 * possible if one of the transactions in question is blocked trying
2274 * to acquire an exclusive lock on our table. The lock code will
2275 * detect deadlock and error out properly.
2276 *
2277 * Note: we report progress through WaitForLockers() unconditionally
2278 * here, even though it will only be used when we're called by REINDEX
2279 * CONCURRENTLY and not when called by DROP INDEX CONCURRENTLY.
2280 */
2282
2283 /*
2284 * Updating pg_index might involve TOAST table access, so ensure we
2285 * have a valid snapshot.
2286 */
2288
2289 /* Finish invalidation of index and mark it as dead */
2291
2293
2294 /*
2295 * Again, commit the transaction to make the pg_index update visible
2296 * to other sessions.
2297 */
2300
2301 /*
2302 * Wait till every transaction that saw the old index state has
2303 * finished. See above about progress reporting.
2304 */
2306
2307 /*
2308 * Re-open relations to allow us to complete our actions.
2309 *
2310 * At this point, nothing should be accessing the index, but lets
2311 * leave nothing to chance and grab AccessExclusiveLock on the index
2312 * before the physical deletion.
2313 */
2316 }
2317 else
2318 {
2319 /* Not concurrent, so just transfer predicate locks and we're good */
2321 }
2322
2323 /*
2324 * Schedule physical removal of the files (if any)
2325 */
2326 if (RELKIND_HAS_STORAGE(userIndexRelation->rd_rel->relkind))
2328
2329 /* ensure that stats are dropped if transaction commits */
2331
2332 /*
2333 * Close and flush the index's relcache entry, to ensure relcache doesn't
2334 * try to rebuild it while we're deleting catalog entries. We keep the
2335 * lock though.
2336 */
2338
2340
2341 /*
2342 * Updating pg_index might involve TOAST table access, so ensure we have a
2343 * valid snapshot.
2344 */
2346
2347 /*
2348 * fix INDEX relation, and check for expressional index
2349 */
2351
2353 if (!HeapTupleIsValid(tuple))
2354 elog(ERROR, "cache lookup failed for index %u", indexId);
2355
2357 RelationGetDescr(indexRelation));
2358
2359 CatalogTupleDelete(indexRelation, &tuple->t_self);
2360
2361 ReleaseSysCache(tuple);
2362 table_close(indexRelation, RowExclusiveLock);
2363
2365
2366 /*
2367 * if it has any expression columns, we might have stored statistics about
2368 * them.
2369 */
2370 if (hasexprs)
2372
2373 /*
2374 * fix ATTRIBUTE relation
2375 */
2377
2378 /*
2379 * fix RELATION relation
2380 */
2382
2383 /*
2384 * fix INHERITS relation
2385 */
2387
2388 /*
2389 * We are presently too lazy to attempt to compute the new correct value
2390 * of relhasindex (the next VACUUM will fix it if necessary). So there is
2391 * no need to update the pg_class tuple for the owning relation. But we
2392 * must send out a shared-cache-inval notice on the owning relation to
2393 * ensure other backends update their relcache lists of indexes. (In the
2394 * concurrent case, this is redundant but harmless.)
2395 */
2397
2398 /*
2399 * Close owning rel, but keep lock
2400 */
2402
2403 /*
2404 * Release the session locks before we go.
2405 */
2406 if (concurrent)
2407 {
2410 }
2411}
2412
2413/* ----------------------------------------------------------------
2414 * index_build support
2415 * ----------------------------------------------------------------
2416 */
2417
2418/* ----------------
2419 * BuildIndexInfo
2420 * Construct an IndexInfo record for an open index
2421 *
2422 * IndexInfo stores the information about the index that's needed by
2423 * FormIndexDatum, which is used for both index_build() and later insertion
2424 * of individual index tuples. Normally we build an IndexInfo for an index
2425 * just once per command, and then use it for (potentially) many tuples.
2426 * ----------------
2427 */
2428IndexInfo *
2430{
2431 IndexInfo *ii;
2432 Form_pg_index indexStruct = index->rd_index;
2433 int i;
2434 int numAtts;
2435
2436 /* check the number of keys, and copy attr numbers into the IndexInfo */
2437 numAtts = indexStruct->indnatts;
2439 elog(ERROR, "invalid indnatts %d for index %u",
2441
2442 /*
2443 * Create the node, fetching any expressions needed for expressional
2444 * indexes and index predicate if any.
2445 */
2446 ii = makeIndexInfo(indexStruct->indnatts,
2447 indexStruct->indnkeyatts,
2448 index->rd_rel->relam,
2451 indexStruct->indisunique,
2452 indexStruct->indnullsnotdistinct,
2453 indexStruct->indisready,
2454 false,
2455 index->rd_indam->amsummarizing,
2456 indexStruct->indisexclusion && indexStruct->indisunique);
2457
2458 /* fill in attribute numbers */
2459 for (i = 0; i < numAtts; i++)
2460 ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i];
2461
2462 /* fetch exclusion constraint info if any */
2463 if (indexStruct->indisexclusion)
2464 {
2466 &ii->ii_ExclusionOps,
2467 &ii->ii_ExclusionProcs,
2468 &ii->ii_ExclusionStrats);
2469 }
2470
2471 return ii;
2472}
2473
2474/* ----------------
2475 * BuildDummyIndexInfo
2476 * Construct a dummy IndexInfo record for an open index
2477 *
2478 * This differs from the real BuildIndexInfo in that it will never run any
2479 * user-defined code that might exist in index expressions or predicates.
2480 * Instead of the real index expressions, we return null constants that have
2481 * the right types/typmods/collations. Predicates and exclusion clauses are
2482 * just ignored. This is sufficient for the purpose of truncating an index,
2483 * since we will not need to actually evaluate the expressions or predicates;
2484 * the only thing that's likely to be done with the data is construction of
2485 * a tupdesc describing the index's rowtype.
2486 * ----------------
2487 */
2488IndexInfo *
2490{
2491 IndexInfo *ii;
2492 Form_pg_index indexStruct = index->rd_index;
2493 int i;
2494 int numAtts;
2495
2496 /* check the number of keys, and copy attr numbers into the IndexInfo */
2497 numAtts = indexStruct->indnatts;
2499 elog(ERROR, "invalid indnatts %d for index %u",
2501
2502 /*
2503 * Create the node, using dummy index expressions, and pretending there is
2504 * no predicate.
2505 */
2506 ii = makeIndexInfo(indexStruct->indnatts,
2507 indexStruct->indnkeyatts,
2508 index->rd_rel->relam,
2510 NIL,
2511 indexStruct->indisunique,
2512 indexStruct->indnullsnotdistinct,
2513 indexStruct->indisready,
2514 false,
2515 index->rd_indam->amsummarizing,
2516 indexStruct->indisexclusion && indexStruct->indisunique);
2517
2518 /* fill in attribute numbers */
2519 for (i = 0; i < numAtts; i++)
2520 ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i];
2521
2522 /* We ignore the exclusion constraint if any */
2523
2524 return ii;
2525}
2526
2527/*
2528 * CompareIndexInfo
2529 * Return whether the properties of two indexes (in different tables)
2530 * indicate that they have the "same" definitions.
2531 *
2532 * Note: passing collations and opfamilies separately is a kludge. Adding
2533 * them to IndexInfo may result in better coding here and elsewhere.
2534 *
2535 * Use build_attrmap_by_name(index2, index1) to build the attmap.
2536 */
2537bool
2539 const Oid *collations1, const Oid *collations2,
2540 const Oid *opfamilies1, const Oid *opfamilies2,
2541 const AttrMap *attmap)
2542{
2543 int i;
2544
2545 if (info1->ii_Unique != info2->ii_Unique)
2546 return false;
2547
2548 if (info1->ii_NullsNotDistinct != info2->ii_NullsNotDistinct)
2549 return false;
2550
2551 /* indexes are only equivalent if they have the same access method */
2552 if (info1->ii_Am != info2->ii_Am)
2553 return false;
2554
2555 /* and same number of attributes */
2556 if (info1->ii_NumIndexAttrs != info2->ii_NumIndexAttrs)
2557 return false;
2558
2559 /* and same number of key attributes */
2560 if (info1->ii_NumIndexKeyAttrs != info2->ii_NumIndexKeyAttrs)
2561 return false;
2562
2563 /*
2564 * and columns match through the attribute map (actual attribute numbers
2565 * might differ!) Note that this checks that index columns that are
2566 * expressions appear in the same positions. We will next compare the
2567 * expressions themselves.
2568 */
2569 for (i = 0; i < info1->ii_NumIndexAttrs; i++)
2570 {
2571 if (attmap->maplen < info2->ii_IndexAttrNumbers[i])
2572 elog(ERROR, "incorrect attribute map");
2573
2574 /* ignore expressions for now (but check their collation/opfamily) */
2575 if (!(info1->ii_IndexAttrNumbers[i] == InvalidAttrNumber &&
2576 info2->ii_IndexAttrNumbers[i] == InvalidAttrNumber))
2577 {
2578 /* fail if just one index has an expression in this column */
2579 if (info1->ii_IndexAttrNumbers[i] == InvalidAttrNumber ||
2580 info2->ii_IndexAttrNumbers[i] == InvalidAttrNumber)
2581 return false;
2582
2583 /* both are columns, so check for match after mapping */
2584 if (attmap->attnums[info2->ii_IndexAttrNumbers[i] - 1] !=
2585 info1->ii_IndexAttrNumbers[i])
2586 return false;
2587 }
2588
2589 /* collation and opfamily are not valid for included columns */
2590 if (i >= info1->ii_NumIndexKeyAttrs)
2591 continue;
2592
2593 if (collations1[i] != collations2[i])
2594 return false;
2595 if (opfamilies1[i] != opfamilies2[i])
2596 return false;
2597 }
2598
2599 /*
2600 * For expression indexes: either both are expression indexes, or neither
2601 * is; if they are, make sure the expressions match.
2602 */
2603 if ((info1->ii_Expressions != NIL) != (info2->ii_Expressions != NIL))
2604 return false;
2605 if (info1->ii_Expressions != NIL)
2606 {
2607 bool found_whole_row;
2608 Node *mapped;
2609
2610 mapped = map_variable_attnos((Node *) info2->ii_Expressions,
2611 1, 0, attmap,
2612 InvalidOid, &found_whole_row);
2613 if (found_whole_row)
2614 {
2615 /*
2616 * we could throw an error here, but seems out of scope for this
2617 * routine.
2618 */
2619 return false;
2620 }
2621
2622 if (!equal(info1->ii_Expressions, mapped))
2623 return false;
2624 }
2625
2626 /* Partial index predicates must be identical, if they exist */
2627 if ((info1->ii_Predicate == NULL) != (info2->ii_Predicate == NULL))
2628 return false;
2629 if (info1->ii_Predicate != NULL)
2630 {
2631 bool found_whole_row;
2632 Node *mapped;
2633
2634 mapped = map_variable_attnos((Node *) info2->ii_Predicate,
2635 1, 0, attmap,
2636 InvalidOid, &found_whole_row);
2637 if (found_whole_row)
2638 {
2639 /*
2640 * we could throw an error here, but seems out of scope for this
2641 * routine.
2642 */
2643 return false;
2644 }
2645 if (!equal(info1->ii_Predicate, mapped))
2646 return false;
2647 }
2648
2649 /* No support currently for comparing exclusion indexes. */
2650 if (info1->ii_ExclusionOps != NULL || info2->ii_ExclusionOps != NULL)
2651 return false;
2652
2653 return true;
2654}
2655
2656/* ----------------
2657 * BuildSpeculativeIndexInfo
2658 * Add extra state to IndexInfo record
2659 *
2660 * For unique indexes, we usually don't want to add info to the IndexInfo for
2661 * checking uniqueness, since the B-Tree AM handles that directly. However, in
2662 * the case of speculative insertion and conflict detection in logical
2663 * replication, additional support is required.
2664 *
2665 * Do this processing here rather than in BuildIndexInfo() to not incur the
2666 * overhead in the common non-speculative cases.
2667 * ----------------
2668 */
2669void
2671{
2672 int indnkeyatts;
2673 int i;
2674
2676
2677 /*
2678 * fetch info for checking unique indexes
2679 */
2680 Assert(ii->ii_Unique);
2681
2685
2686 /*
2687 * We have to look up the operator's strategy number. This provides a
2688 * cross-check that the operator does match the index.
2689 */
2690 /* We need the func OIDs and strategy numbers too */
2691 for (i = 0; i < indnkeyatts; i++)
2692 {
2693 ii->ii_UniqueStrats[i] =
2695 index->rd_rel->relam,
2696 index->rd_opfamily[i],
2697 false);
2698 ii->ii_UniqueOps[i] =
2699 get_opfamily_member(index->rd_opfamily[i],
2700 index->rd_opcintype[i],
2701 index->rd_opcintype[i],
2702 ii->ii_UniqueStrats[i]);
2703 if (!OidIsValid(ii->ii_UniqueOps[i]))
2704 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
2705 ii->ii_UniqueStrats[i], index->rd_opcintype[i],
2706 index->rd_opcintype[i], index->rd_opfamily[i]);
2708 }
2709}
2710
2711/* ----------------
2712 * FormIndexDatum
2713 * Construct values[] and isnull[] arrays for a new index tuple.
2714 *
2715 * indexInfo Info about the index
2716 * slot Heap tuple for which we must prepare an index entry
2717 * estate executor state for evaluating any index expressions
2718 * values Array of index Datums (output area)
2719 * isnull Array of is-null indicators (output area)
2720 *
2721 * When there are no index expressions, estate may be NULL. Otherwise it
2722 * must be supplied, *and* the ecxt_scantuple slot of its per-tuple expr
2723 * context must point to the heap tuple passed in.
2724 *
2725 * Notice we don't actually call index_form_tuple() here; we just prepare
2726 * its input arrays values[] and isnull[]. This is because the index AM
2727 * may wish to alter the data before storage.
2728 * ----------------
2729 */
2730void
2732 TupleTableSlot *slot,
2733 EState *estate,
2734 Datum *values,
2735 bool *isnull)
2736{
2738 int i;
2739
2740 if (indexInfo->ii_Expressions != NIL &&
2741 indexInfo->ii_ExpressionsState == NIL)
2742 {
2743 /* First time through, set up expression evaluation state */
2744 indexInfo->ii_ExpressionsState =
2745 ExecPrepareExprList(indexInfo->ii_Expressions, estate);
2746 /* Check caller has set up context correctly */
2747 Assert(GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
2748 }
2750
2751 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
2752 {
2753 int keycol = indexInfo->ii_IndexAttrNumbers[i];
2754 Datum iDatum;
2755 bool isNull;
2756
2757 if (keycol < 0)
2758 iDatum = slot_getsysattr(slot, keycol, &isNull);
2759 else if (keycol != 0)
2760 {
2761 /*
2762 * Plain index column; get the value we need directly from the
2763 * heap tuple.
2764 */
2765 iDatum = slot_getattr(slot, keycol, &isNull);
2766 }
2767 else
2768 {
2769 /*
2770 * Index expression --- need to evaluate it.
2771 */
2772 if (indexpr_item == NULL)
2773 elog(ERROR, "wrong number of index expressions");
2775 GetPerTupleExprContext(estate),
2776 &isNull);
2778 }
2779 values[i] = iDatum;
2780 isnull[i] = isNull;
2781 }
2782
2783 if (indexpr_item != NULL)
2784 elog(ERROR, "wrong number of index expressions");
2785}
2786
2787
2788/*
2789 * index_update_stats --- update pg_class entry after CREATE INDEX or REINDEX
2790 *
2791 * This routine updates the pg_class row of either an index or its parent
2792 * relation after CREATE INDEX or REINDEX. Its rather bizarre API is designed
2793 * to ensure we can do all the necessary work in just one update.
2794 *
2795 * hasindex: set relhasindex to this value
2796 * reltuples: if >= 0, set reltuples to this value; else no change
2797 *
2798 * If reltuples >= 0, relpages, relallvisible, and relallfrozen are also
2799 * updated (using RelationGetNumberOfBlocks() and visibilitymap_count()).
2800 *
2801 * NOTE: an important side-effect of this operation is that an SI invalidation
2802 * message is sent out to all backends --- including me --- causing relcache
2803 * entries to be flushed or updated with the new data. This must happen even
2804 * if we find that no change is needed in the pg_class row. When updating
2805 * a heap entry, this ensures that other backends find out about the new
2806 * index. When updating an index, it's important because some index AMs
2807 * expect a relcache flush to occur after REINDEX.
2808 */
2809static void
2811 bool hasindex,
2812 double reltuples)
2813{
2814 bool update_stats;
2815 BlockNumber relpages = 0; /* keep compiler quiet */
2816 BlockNumber relallvisible = 0;
2817 BlockNumber relallfrozen = 0;
2818 Oid relid = RelationGetRelid(rel);
2820 ScanKeyData key[1];
2821 HeapTuple tuple;
2822 void *state;
2823 Form_pg_class rd_rel;
2824 bool dirty;
2825
2826 /*
2827 * As a special hack, if we are dealing with an empty table and the
2828 * existing reltuples is -1, we leave that alone. This ensures that
2829 * creating an index as part of CREATE TABLE doesn't cause the table to
2830 * prematurely look like it's been vacuumed. The rd_rel we modify may
2831 * differ from rel->rd_rel due to e.g. commit of concurrent GRANT, but the
2832 * commands that change reltuples take locks conflicting with ours. (Even
2833 * if a command changed reltuples under a weaker lock, this affects only
2834 * statistics for an empty table.)
2835 */
2836 if (reltuples == 0 && rel->rd_rel->reltuples < 0)
2837 reltuples = -1;
2838
2839 /*
2840 * Don't update statistics during binary upgrade, because the indexes are
2841 * created before the data is moved into place.
2842 */
2843 update_stats = reltuples >= 0 && !IsBinaryUpgrade;
2844
2845 /*
2846 * If autovacuum is off, user may not be expecting table relstats to
2847 * change. This can be important when restoring a dump that includes
2848 * statistics, as the table statistics may be restored before the index is
2849 * created, and we want to preserve the restored table statistics.
2850 */
2851 if (rel->rd_rel->relkind == RELKIND_RELATION ||
2852 rel->rd_rel->relkind == RELKIND_TOASTVALUE ||
2853 rel->rd_rel->relkind == RELKIND_MATVIEW)
2854 {
2855 if (AutoVacuumingActive())
2856 {
2858
2859 if (options != NULL && !options->autovacuum.enabled)
2860 update_stats = false;
2861 }
2862 else
2863 update_stats = false;
2864 }
2865
2866 /*
2867 * Finish I/O and visibility map buffer locks before
2868 * systable_inplace_update_begin() locks the pg_class buffer. The rd_rel
2869 * we modify may differ from rel->rd_rel due to e.g. commit of concurrent
2870 * GRANT, but no command changes a relkind from non-index to index. (Even
2871 * if one did, relallvisible doesn't break functionality.)
2872 */
2873 if (update_stats)
2874 {
2875 relpages = RelationGetNumberOfBlocks(rel);
2876
2877 if (rel->rd_rel->relkind != RELKIND_INDEX)
2878 visibilitymap_count(rel, &relallvisible, &relallfrozen);
2879 }
2880
2881 /*
2882 * We always update the pg_class row using a non-transactional,
2883 * overwrite-in-place update. There are several reasons for this:
2884 *
2885 * 1. In bootstrap mode, we have no choice --- UPDATE wouldn't work.
2886 *
2887 * 2. We could be reindexing pg_class itself, in which case we can't move
2888 * its pg_class row because CatalogTupleInsert/CatalogTupleUpdate might
2889 * not know about all the indexes yet (see reindex_relation).
2890 *
2891 * 3. Because we execute CREATE INDEX with just share lock on the parent
2892 * rel (to allow concurrent index creations), an ordinary update could
2893 * suffer a tuple-concurrently-updated failure against another CREATE
2894 * INDEX committing at about the same time. We can avoid that by having
2895 * them both do nontransactional updates (we assume they will both be
2896 * trying to change the pg_class row to the same thing, so it doesn't
2897 * matter which goes first).
2898 *
2899 * It is safe to use a non-transactional update even though our
2900 * transaction could still fail before committing. Setting relhasindex
2901 * true is safe even if there are no indexes (VACUUM will eventually fix
2902 * it). And of course the new relpages and reltuples counts are correct
2903 * regardless. However, we don't want to change relpages (or
2904 * relallvisible) if the caller isn't providing an updated reltuples
2905 * count, because that would bollix the reltuples/relpages ratio which is
2906 * what's really important.
2907 */
2908
2910
2911 ScanKeyInit(&key[0],
2914 ObjectIdGetDatum(relid));
2916 1, key, &tuple, &state);
2917
2918 if (!HeapTupleIsValid(tuple))
2919 elog(ERROR, "could not find tuple for relation %u", relid);
2920 rd_rel = (Form_pg_class) GETSTRUCT(tuple);
2921
2922 /* Should this be a more comprehensive test? */
2923 Assert(rd_rel->relkind != RELKIND_PARTITIONED_INDEX);
2924
2925 /* Apply required updates, if any, to copied tuple */
2926
2927 dirty = false;
2928 if (rd_rel->relhasindex != hasindex)
2929 {
2930 rd_rel->relhasindex = hasindex;
2931 dirty = true;
2932 }
2933
2934 if (update_stats)
2935 {
2936 if (rd_rel->relpages != (int32) relpages)
2937 {
2938 rd_rel->relpages = (int32) relpages;
2939 dirty = true;
2940 }
2941 if (rd_rel->reltuples != (float4) reltuples)
2942 {
2943 rd_rel->reltuples = (float4) reltuples;
2944 dirty = true;
2945 }
2946 if (rd_rel->relallvisible != (int32) relallvisible)
2947 {
2948 rd_rel->relallvisible = (int32) relallvisible;
2949 dirty = true;
2950 }
2951 if (rd_rel->relallfrozen != (int32) relallfrozen)
2952 {
2953 rd_rel->relallfrozen = (int32) relallfrozen;
2954 dirty = true;
2955 }
2956 }
2957
2958 /*
2959 * If anything changed, write out the tuple
2960 */
2961 if (dirty)
2962 {
2964 /* the above sends transactional and immediate cache inval messages */
2965 }
2966 else
2967 {
2969
2970 /*
2971 * While we didn't change relhasindex, CREATE INDEX needs a
2972 * transactional inval for when the new index's catalog rows become
2973 * visible. Other CREATE INDEX and REINDEX code happens to also queue
2974 * this inval, but keep this in case rare callers rely on this part of
2975 * our API contract.
2976 */
2978 }
2979
2980 heap_freetuple(tuple);
2981
2983}
2984
2985
2986/*
2987 * index_build - invoke access-method-specific index build procedure
2988 *
2989 * On entry, the index's catalog entries are valid, and its physical disk
2990 * file has been created but is empty. We call the AM-specific build
2991 * procedure to fill in the index contents. We then update the pg_class
2992 * entries of the index and heap relation as needed, using statistics
2993 * returned by ambuild as well as data passed by the caller.
2994 *
2995 * isreindex indicates we are recreating a previously-existing index.
2996 * parallel indicates if parallelism may be useful.
2997 *
2998 * Note: before Postgres 8.2, the passed-in heap and index Relations
2999 * were automatically closed by this routine. This is no longer the case.
3000 * The caller opened 'em, and the caller should close 'em.
3001 */
3002void
3004 Relation indexRelation,
3005 IndexInfo *indexInfo,
3006 bool isreindex,
3007 bool parallel)
3008{
3009 IndexBuildResult *stats;
3010 Oid save_userid;
3011 int save_sec_context;
3012 int save_nestlevel;
3013
3014 /*
3015 * sanity checks
3016 */
3017 Assert(RelationIsValid(indexRelation));
3018 Assert(indexRelation->rd_indam);
3019 Assert(indexRelation->rd_indam->ambuild);
3020 Assert(indexRelation->rd_indam->ambuildempty);
3021
3022 /*
3023 * Determine worker process details for parallel CREATE INDEX. Currently,
3024 * only btree, GIN, and BRIN have support for parallel builds.
3025 *
3026 * Note that planner considers parallel safety for us.
3027 */
3029 indexRelation->rd_indam->amcanbuildparallel)
3030 indexInfo->ii_ParallelWorkers =
3032 RelationGetRelid(indexRelation));
3033
3034 if (indexInfo->ii_ParallelWorkers == 0)
3036 (errmsg_internal("building index \"%s\" on table \"%s\" serially",
3037 RelationGetRelationName(indexRelation),
3038 RelationGetRelationName(heapRelation))));
3039 else
3041 (errmsg_internal("building index \"%s\" on table \"%s\" with request for %d parallel workers",
3042 RelationGetRelationName(indexRelation),
3043 RelationGetRelationName(heapRelation),
3044 indexInfo->ii_ParallelWorkers)));
3045
3046 /*
3047 * Switch to the table owner's userid, so that any index functions are run
3048 * as that user. Also lock down security-restricted operations and
3049 * arrange to make GUC variable changes local to this command.
3050 */
3051 GetUserIdAndSecContext(&save_userid, &save_sec_context);
3052 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3053 save_sec_context | SECURITY_RESTRICTED_OPERATION);
3054 save_nestlevel = NewGUCNestLevel();
3056
3057 /* Set up initial progress report status */
3058 {
3059 const int progress_index[] = {
3066 };
3067 const int64 progress_vals[] = {
3070 0, 0, 0, 0
3071 };
3072
3074 }
3075
3076 /*
3077 * Call the access method's build procedure
3078 */
3079 stats = indexRelation->rd_indam->ambuild(heapRelation, indexRelation,
3080 indexInfo);
3081 Assert(stats);
3082
3083 /*
3084 * If this is an unlogged index, we may need to write out an init fork for
3085 * it -- but we must first check whether one already exists. If, for
3086 * example, an unlogged relation is truncated in the transaction that
3087 * created it, or truncated twice in a subsequent transaction, the
3088 * relfilenumber won't change, and nothing needs to be done here.
3089 */
3090 if (indexRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
3091 !smgrexists(RelationGetSmgr(indexRelation), INIT_FORKNUM))
3092 {
3093 smgrcreate(RelationGetSmgr(indexRelation), INIT_FORKNUM, false);
3094 log_smgrcreate(&indexRelation->rd_locator, INIT_FORKNUM);
3095 indexRelation->rd_indam->ambuildempty(indexRelation);
3096 }
3097
3098 /*
3099 * If we found any potentially broken HOT chains, mark the index as not
3100 * being usable until the current transaction is below the event horizon.
3101 * See src/backend/access/heap/README.HOT for discussion. While it might
3102 * become safe to use the index earlier based on actual cleanup activity
3103 * and other active transactions, the test for that would be much more
3104 * complex and would require some form of blocking, so keep it simple and
3105 * fast by just using the current transaction.
3106 *
3107 * However, when reindexing an existing index, we should do nothing here.
3108 * Any HOT chains that are broken with respect to the index must predate
3109 * the index's original creation, so there is no need to change the
3110 * index's usability horizon. Moreover, we *must not* try to change the
3111 * index's pg_index entry while reindexing pg_index itself, and this
3112 * optimization nicely prevents that. The more complex rules needed for a
3113 * reindex are handled separately after this function returns.
3114 *
3115 * We also need not set indcheckxmin during a concurrent index build,
3116 * because we won't set indisvalid true until all transactions that care
3117 * about the broken HOT chains are gone.
3118 *
3119 * Therefore, this code path can only be taken during non-concurrent
3120 * CREATE INDEX. Thus the fact that heap_update will set the pg_index
3121 * tuple's xmin doesn't matter, because that tuple was created in the
3122 * current transaction anyway. That also means we don't need to worry
3123 * about any concurrent readers of the tuple; no other transaction can see
3124 * it yet.
3125 */
3126 if (indexInfo->ii_BrokenHotChain &&
3127 !isreindex &&
3128 !indexInfo->ii_Concurrent)
3129 {
3130 Oid indexId = RelationGetRelid(indexRelation);
3134
3136
3140 elog(ERROR, "cache lookup failed for index %u", indexId);
3142
3143 /* If it's a new index, indcheckxmin shouldn't be set ... */
3144 Assert(!indexForm->indcheckxmin);
3145
3146 indexForm->indcheckxmin = true;
3148
3151 }
3152
3153 /*
3154 * Update heap and index pg_class rows
3155 */
3156 index_update_stats(heapRelation,
3157 true,
3158 stats->heap_tuples);
3159
3160 index_update_stats(indexRelation,
3161 false,
3162 stats->index_tuples);
3163
3164 /* Make the updated catalog row versions visible */
3166
3167 /*
3168 * If it's for an exclusion constraint, make a second pass over the heap
3169 * to verify that the constraint is satisfied. We must not do this until
3170 * the index is fully valid. (Broken HOT chains shouldn't matter, though;
3171 * see comments for IndexCheckExclusion.)
3172 */
3173 if (indexInfo->ii_ExclusionOps != NULL)
3174 IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
3175
3176 /* Roll back any GUC changes executed by index functions */
3177 AtEOXact_GUC(false, save_nestlevel);
3178
3179 /* Restore userid and security context */
3180 SetUserIdAndSecContext(save_userid, save_sec_context);
3181}
3182
3183/*
3184 * IndexCheckExclusion - verify that a new exclusion constraint is satisfied
3185 *
3186 * When creating an exclusion constraint, we first build the index normally
3187 * and then rescan the heap to check for conflicts. We assume that we only
3188 * need to validate tuples that are live according to an up-to-date snapshot,
3189 * and that these were correctly indexed even in the presence of broken HOT
3190 * chains. This should be OK since we are holding at least ShareLock on the
3191 * table, meaning there can be no uncommitted updates from other transactions.
3192 * (Note: that wouldn't necessarily work for system catalogs, since many
3193 * operations release write lock early on the system catalogs.)
3194 */
3195static void
3197 Relation indexRelation,
3198 IndexInfo *indexInfo)
3199{
3200 TableScanDesc scan;
3202 bool isnull[INDEX_MAX_KEYS];
3204 TupleTableSlot *slot;
3205 EState *estate;
3206 ExprContext *econtext;
3207 Snapshot snapshot;
3208
3209 /*
3210 * If we are reindexing the target index, mark it as no longer being
3211 * reindexed, to forestall an Assert in index_beginscan when we try to use
3212 * the index for probes. This is OK because the index is now fully valid.
3213 */
3216
3217 /*
3218 * Need an EState for evaluation of index expressions and partial-index
3219 * predicates. Also a slot to hold the current tuple.
3220 */
3221 estate = CreateExecutorState();
3222 econtext = GetPerTupleExprContext(estate);
3223 slot = table_slot_create(heapRelation, NULL);
3224
3225 /* Arrange for econtext's scan tuple to be the tuple under test */
3226 econtext->ecxt_scantuple = slot;
3227
3228 /* Set up execution state for predicate, if any. */
3229 predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
3230
3231 /*
3232 * Scan all live tuples in the base relation.
3233 */
3234 snapshot = RegisterSnapshot(GetLatestSnapshot());
3235 scan = table_beginscan_strat(heapRelation, /* relation */
3236 snapshot, /* snapshot */
3237 0, /* number of keys */
3238 NULL, /* scan key */
3239 true, /* buffer access strategy OK */
3240 true); /* syncscan OK */
3241
3242 while (table_scan_getnextslot(scan, ForwardScanDirection, slot))
3243 {
3245
3246 /*
3247 * In a partial index, ignore tuples that don't satisfy the predicate.
3248 */
3249 if (predicate != NULL)
3250 {
3251 if (!ExecQual(predicate, econtext))
3252 continue;
3253 }
3254
3255 /*
3256 * Extract index column values, including computing expressions.
3257 */
3258 FormIndexDatum(indexInfo,
3259 slot,
3260 estate,
3261 values,
3262 isnull);
3263
3264 /*
3265 * Check that this tuple has no conflicts.
3266 */
3267 check_exclusion_constraint(heapRelation,
3268 indexRelation, indexInfo,
3269 &(slot->tts_tid), values, isnull,
3270 estate, true);
3271
3273 }
3274
3275 table_endscan(scan);
3276 UnregisterSnapshot(snapshot);
3277
3279
3280 FreeExecutorState(estate);
3281
3282 /* These may have been pointing to the now-gone estate */
3283 indexInfo->ii_ExpressionsState = NIL;
3284 indexInfo->ii_PredicateState = NULL;
3285}
3286
3287/*
3288 * validate_index - support code for concurrent index builds
3289 *
3290 * We do a concurrent index build by first inserting the catalog entry for the
3291 * index via index_create(), marking it not indisready and not indisvalid.
3292 * Then we commit our transaction and start a new one, then we wait for all
3293 * transactions that could have been modifying the table to terminate. Now
3294 * we know that any subsequently-started transactions will see the index and
3295 * honor its constraints on HOT updates; so while existing HOT-chains might
3296 * be broken with respect to the index, no currently live tuple will have an
3297 * incompatible HOT update done to it. We now build the index normally via
3298 * index_build(), while holding a weak lock that allows concurrent
3299 * insert/update/delete. Also, we index only tuples that are valid
3300 * as of the start of the scan (see table_index_build_scan), whereas a normal
3301 * build takes care to include recently-dead tuples. This is OK because
3302 * we won't mark the index valid until all transactions that might be able
3303 * to see those tuples are gone. The reason for doing that is to avoid
3304 * bogus unique-index failures due to concurrent UPDATEs (we might see
3305 * different versions of the same row as being valid when we pass over them,
3306 * if we used HeapTupleSatisfiesVacuum). This leaves us with an index that
3307 * does not contain any tuples added to the table while we built the index.
3308 *
3309 * Next, we mark the index "indisready" (but still not "indisvalid") and
3310 * commit the second transaction and start a third. Again we wait for all
3311 * transactions that could have been modifying the table to terminate. Now
3312 * we know that any subsequently-started transactions will see the index and
3313 * insert their new tuples into it. We then take a new reference snapshot
3314 * which is passed to validate_index(). Any tuples that are valid according
3315 * to this snap, but are not in the index, must be added to the index.
3316 * (Any tuples committed live after the snap will be inserted into the
3317 * index by their originating transaction. Any tuples committed dead before
3318 * the snap need not be indexed, because we will wait out all transactions
3319 * that might care about them before we mark the index valid.)
3320 *
3321 * validate_index() works by first gathering all the TIDs currently in the
3322 * index, using a bulkdelete callback that just stores the TIDs and doesn't
3323 * ever say "delete it". (This should be faster than a plain indexscan;
3324 * also, not all index AMs support full-index indexscan.) Then we sort the
3325 * TIDs, and finally scan the table doing a "merge join" against the TID list
3326 * to see which tuples are missing from the index. Thus we will ensure that
3327 * all tuples valid according to the reference snapshot are in the index.
3328 *
3329 * Building a unique index this way is tricky: we might try to insert a
3330 * tuple that is already dead or is in process of being deleted, and we
3331 * mustn't have a uniqueness failure against an updated version of the same
3332 * row. We could try to check the tuple to see if it's already dead and tell
3333 * index_insert() not to do the uniqueness check, but that still leaves us
3334 * with a race condition against an in-progress update. To handle that,
3335 * we expect the index AM to recheck liveness of the to-be-inserted tuple
3336 * before it declares a uniqueness error.
3337 *
3338 * After completing validate_index(), we wait until all transactions that
3339 * were alive at the time of the reference snapshot are gone; this is
3340 * necessary to be sure there are none left with a transaction snapshot
3341 * older than the reference (and hence possibly able to see tuples we did
3342 * not index). Then we mark the index "indisvalid" and commit. Subsequent
3343 * transactions will be able to use it for queries.
3344 *
3345 * Doing two full table scans is a brute-force strategy. We could try to be
3346 * cleverer, eg storing new tuples in a special area of the table (perhaps
3347 * making the table append-only by setting use_fsm). However that would
3348 * add yet more locking issues.
3349 */
3350void
3352{
3353 Relation heapRelation,
3354 indexRelation;
3355 IndexInfo *indexInfo;
3358 Oid save_userid;
3359 int save_sec_context;
3360 int save_nestlevel;
3361
3362 {
3363 const int progress_index[] = {
3369 };
3370 const int64 progress_vals[] = {
3372 0, 0, 0, 0
3373 };
3374
3376 }
3377
3378 /* Open and lock the parent heap relation */
3380
3381 /*
3382 * Switch to the table owner's userid, so that any index functions are run
3383 * as that user. Also lock down security-restricted operations and
3384 * arrange to make GUC variable changes local to this command.
3385 */
3386 GetUserIdAndSecContext(&save_userid, &save_sec_context);
3387 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3388 save_sec_context | SECURITY_RESTRICTED_OPERATION);
3389 save_nestlevel = NewGUCNestLevel();
3391
3392 indexRelation = index_open(indexId, RowExclusiveLock);
3393
3394 /*
3395 * Fetch info needed for index_insert. (You might think this should be
3396 * passed in from DefineIndex, but its copy is long gone due to having
3397 * been built in a previous transaction.)
3398 */
3399 indexInfo = BuildIndexInfo(indexRelation);
3400
3401 /* mark build is concurrent just for consistency */
3402 indexInfo->ii_Concurrent = true;
3403
3404 /*
3405 * Scan the index and gather up all the TIDs into a tuplesort object.
3406 */
3407 ivinfo.index = indexRelation;
3408 ivinfo.heaprel = heapRelation;
3409 ivinfo.analyze_only = false;
3410 ivinfo.report_progress = true;
3411 ivinfo.estimated_count = true;
3412 ivinfo.message_level = DEBUG2;
3413 ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
3414 ivinfo.strategy = NULL;
3415
3416 /*
3417 * Encode TIDs as int8 values for the sort, rather than directly sorting
3418 * item pointers. This can be significantly faster, primarily because TID
3419 * is a pass-by-reference type on all platforms, whereas int8 is
3420 * pass-by-value on most platforms.
3421 */
3423 InvalidOid, false,
3426 state.htups = state.itups = state.tups_inserted = 0;
3427
3428 /* ambulkdelete updates progress metrics */
3431
3432 /* Execute the sort */
3433 {
3434 const int progress_index[] = {
3438 };
3439 const int64 progress_vals[] = {
3441 0, 0
3442 };
3443
3445 }
3446 tuplesort_performsort(state.tuplesort);
3447
3448 /*
3449 * Now scan the heap and "merge" it with the index
3450 */
3453 table_index_validate_scan(heapRelation,
3454 indexRelation,
3455 indexInfo,
3456 snapshot,
3457 &state);
3458
3459 /* Done with tuplesort object */
3460 tuplesort_end(state.tuplesort);
3461
3462 /* Make sure to release resources cached in indexInfo (if needed). */
3463 index_insert_cleanup(indexRelation, indexInfo);
3464
3465 elog(DEBUG2,
3466 "validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
3467 state.htups, state.itups, state.tups_inserted);
3468
3469 /* Roll back any GUC changes executed by index functions */
3470 AtEOXact_GUC(false, save_nestlevel);
3471
3472 /* Restore userid and security context */
3473 SetUserIdAndSecContext(save_userid, save_sec_context);
3474
3475 /* Close rels, but keep locks */
3476 index_close(indexRelation, NoLock);
3477 table_close(heapRelation, NoLock);
3478}
3479
3480/*
3481 * validate_index_callback - bulkdelete callback to collect the index TIDs
3482 */
3483static bool
3485{
3487 int64 encoded = itemptr_encode(itemptr);
3488
3489 tuplesort_putdatum(state->tuplesort, Int64GetDatum(encoded), false);
3490 state->itups += 1;
3491 return false; /* never actually delete anything */
3492}
3493
3494/*
3495 * index_set_state_flags - adjust pg_index state flags
3496 *
3497 * This is used during CREATE/DROP INDEX CONCURRENTLY to adjust the pg_index
3498 * flags that denote the index's state.
3499 *
3500 * Note that CatalogTupleUpdate() sends a cache invalidation message for the
3501 * tuple, so other sessions will hear about the update as soon as we commit.
3502 */
3503void
3505{
3509
3510 /* Open pg_index and fetch a writable copy of the index's tuple */
3512
3516 elog(ERROR, "cache lookup failed for index %u", indexId);
3518
3519 /* Perform the requested state change on the copy */
3520 switch (action)
3521 {
3523 /* Set indisready during a CREATE INDEX CONCURRENTLY sequence */
3524 Assert(indexForm->indislive);
3525 Assert(!indexForm->indisready);
3526 Assert(!indexForm->indisvalid);
3527 indexForm->indisready = true;
3528 break;
3530 /* Set indisvalid during a CREATE INDEX CONCURRENTLY sequence */
3531 Assert(indexForm->indislive);
3532 Assert(indexForm->indisready);
3533 Assert(!indexForm->indisvalid);
3534 indexForm->indisvalid = true;
3535 break;
3537
3538 /*
3539 * Clear indisvalid during a DROP INDEX CONCURRENTLY sequence
3540 *
3541 * If indisready == true we leave it set so the index still gets
3542 * maintained by active transactions. We only need to ensure that
3543 * indisvalid is false. (We don't assert that either is initially
3544 * true, though, since we want to be able to retry a DROP INDEX
3545 * CONCURRENTLY that failed partway through.)
3546 *
3547 * Note: the CLUSTER logic assumes that indisclustered cannot be
3548 * set on any invalid index, so clear that flag too. For
3549 * cleanliness, also clear indisreplident.
3550 */
3551 indexForm->indisvalid = false;
3552 indexForm->indisclustered = false;
3553 indexForm->indisreplident = false;
3554 break;
3556
3557 /*
3558 * Clear indisready/indislive during DROP INDEX CONCURRENTLY
3559 *
3560 * We clear both indisready and indislive, because we not only
3561 * want to stop updates, we want to prevent sessions from touching
3562 * the index at all.
3563 */
3564 Assert(!indexForm->indisvalid);
3565 Assert(!indexForm->indisclustered);
3566 Assert(!indexForm->indisreplident);
3567 indexForm->indisready = false;
3568 indexForm->indislive = false;
3569 break;
3570 }
3571
3572 /* ... and update it */
3574
3576}
3577
3578
3579/*
3580 * IndexGetRelation: given an index's relation OID, get the OID of the
3581 * relation it is an index on. Uses the system cache.
3582 */
3583Oid
3585{
3586 HeapTuple tuple;
3588 Oid result;
3589
3591 if (!HeapTupleIsValid(tuple))
3592 {
3593 if (missing_ok)
3594 return InvalidOid;
3595 elog(ERROR, "cache lookup failed for index %u", indexId);
3596 }
3597 index = (Form_pg_index) GETSTRUCT(tuple);
3598 Assert(index->indexrelid == indexId);
3599
3600 result = index->indrelid;
3601 ReleaseSysCache(tuple);
3602 return result;
3603}
3604
3605/*
3606 * reindex_index - This routine is used to recreate a single index
3607 */
3608void
3610 bool skip_constraint_checks, char persistence,
3611 const ReindexParams *params)
3612{
3613 Relation iRel,
3614 heapRelation;
3615 Oid heapId;
3616 Oid save_userid;
3617 int save_sec_context;
3618 int save_nestlevel;
3619 IndexInfo *indexInfo;
3620 volatile bool skipped_constraint = false;
3621 PGRUsage ru0;
3622 bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0);
3623 bool set_tablespace = false;
3624
3626
3627 /*
3628 * Open and lock the parent heap relation. ShareLock is sufficient since
3629 * we only need to be sure no schema or data changes are going on.
3630 */
3632 (params->options & REINDEXOPT_MISSING_OK) != 0);
3633 /* if relation is missing, leave */
3634 if (!OidIsValid(heapId))
3635 return;
3636
3637 if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3638 heapRelation = try_table_open(heapId, ShareLock);
3639 else
3640 heapRelation = table_open(heapId, ShareLock);
3641
3642 /* if relation is gone, leave */
3643 if (!heapRelation)
3644 return;
3645
3646 /*
3647 * Switch to the table owner's userid, so that any index functions are run
3648 * as that user. Also lock down security-restricted operations and
3649 * arrange to make GUC variable changes local to this command.
3650 */
3651 GetUserIdAndSecContext(&save_userid, &save_sec_context);
3652 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3653 save_sec_context | SECURITY_RESTRICTED_OPERATION);
3654 save_nestlevel = NewGUCNestLevel();
3656
3657 if (progress)
3658 {
3659 const int progress_cols[] = {
3662 };
3663 const int64 progress_vals[] = {
3665 indexId
3666 };
3667
3669 heapId);
3671 }
3672
3673 /*
3674 * Open the target index relation and get an exclusive lock on it, to
3675 * ensure that no one else is touching this particular index.
3676 */
3677 if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3679 else
3681
3682 /* if index relation is gone, leave */
3683 if (!iRel)
3684 {
3685 /* Roll back any GUC changes */
3686 AtEOXact_GUC(false, save_nestlevel);
3687
3688 /* Restore userid and security context */
3689 SetUserIdAndSecContext(save_userid, save_sec_context);
3690
3691 /* Close parent heap relation, but keep locks */
3692 table_close(heapRelation, NoLock);
3693 return;
3694 }
3695
3696 if (progress)
3698 iRel->rd_rel->relam);
3699
3700 /*
3701 * If a statement is available, telling that this comes from a REINDEX
3702 * command, collect the index for event triggers.
3703 */
3704 if (stmt)
3705 {
3706 ObjectAddress address;
3707
3711 (const Node *) stmt);
3712 }
3713
3714 /*
3715 * Partitioned indexes should never get processed here, as they have no
3716 * physical storage.
3717 */
3718 if (iRel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
3719 elog(ERROR, "cannot reindex partitioned index \"%s.%s\"",
3722
3723 /*
3724 * Don't allow reindex on temp tables of other backends ... their local
3725 * buffer manager is not going to cope.
3726 */
3728 ereport(ERROR,
3730 errmsg("cannot reindex temporary tables of other sessions")));
3731
3732 /*
3733 * Don't allow reindex of an invalid index on TOAST table. This is a
3734 * leftover from a failed REINDEX CONCURRENTLY, and if rebuilt it would
3735 * not be possible to drop it anymore.
3736 */
3739 ereport(ERROR,
3741 errmsg("cannot reindex invalid index on TOAST table")));
3742
3743 /*
3744 * System relations cannot be moved even if allow_system_table_mods is
3745 * enabled to keep things consistent with the concurrent case where all
3746 * the indexes of a relation are processed in series, including indexes of
3747 * toast relations.
3748 *
3749 * Note that this check is not part of CheckRelationTableSpaceMove() as it
3750 * gets used for ALTER TABLE SET TABLESPACE that could cascade across
3751 * toast relations.
3752 */
3753 if (OidIsValid(params->tablespaceOid) &&
3755 ereport(ERROR,
3757 errmsg("cannot move system relation \"%s\"",
3759
3760 /* Check if the tablespace of this index needs to be changed */
3761 if (OidIsValid(params->tablespaceOid) &&
3763 set_tablespace = true;
3764
3765 /*
3766 * Also check for active uses of the index in the current transaction; we
3767 * don't want to reindex underneath an open indexscan.
3768 */
3769 CheckTableNotInUse(iRel, "REINDEX INDEX");
3770
3771 /* Set new tablespace, if requested */
3772 if (set_tablespace)
3773 {
3774 /* Update its pg_class row */
3776
3777 /*
3778 * Schedule unlinking of the old index storage at transaction commit.
3779 */
3782
3783 /* Make sure the reltablespace change is visible */
3785 }
3786
3787 /*
3788 * All predicate locks on the index are about to be made invalid. Promote
3789 * them to relation locks on the heap.
3790 */
3792
3793 /* Fetch info needed for index_build */
3794 indexInfo = BuildIndexInfo(iRel);
3795
3796 /* If requested, skip checking uniqueness/exclusion constraints */
3798 {
3799 if (indexInfo->ii_Unique || indexInfo->ii_ExclusionOps != NULL)
3800 skipped_constraint = true;
3801 indexInfo->ii_Unique = false;
3802 indexInfo->ii_ExclusionOps = NULL;
3803 indexInfo->ii_ExclusionProcs = NULL;
3804 indexInfo->ii_ExclusionStrats = NULL;
3805 }
3806
3807 /* Suppress use of the target index while rebuilding it */
3809
3810 /* Create a new physical relation for the index */
3811 RelationSetNewRelfilenumber(iRel, persistence);
3812
3813 /* Initialize the index and rebuild */
3814 /* Note: we do not need to re-establish pkey setting */
3815 index_build(heapRelation, iRel, indexInfo, true, true);
3816
3817 /* Re-allow use of target index */
3819
3820 /*
3821 * If the index is marked invalid/not-ready/dead (ie, it's from a failed
3822 * CREATE INDEX CONCURRENTLY, or a DROP INDEX CONCURRENTLY failed midway),
3823 * and we didn't skip a uniqueness check, we can now mark it valid. This
3824 * allows REINDEX to be used to clean up in such cases.
3825 *
3826 * We can also reset indcheckxmin, because we have now done a
3827 * non-concurrent index build, *except* in the case where index_build
3828 * found some still-broken HOT chains. If it did, and we don't have to
3829 * change any of the other flags, we just leave indcheckxmin alone (note
3830 * that index_build won't have changed it, because this is a reindex).
3831 * This is okay and desirable because not updating the tuple leaves the
3832 * index's usability horizon (recorded as the tuple's xmin value) the same
3833 * as it was.
3834 *
3835 * But, if the index was invalid/not-ready/dead and there were broken HOT
3836 * chains, we had better force indcheckxmin true, because the normal
3837 * argument that the HOT chains couldn't conflict with the index is
3838 * suspect for an invalid index. (A conflict is definitely possible if
3839 * the index was dead. It probably shouldn't happen otherwise, but let's
3840 * be conservative.) In this case advancing the usability horizon is
3841 * appropriate.
3842 *
3843 * Another reason for avoiding unnecessary updates here is that while
3844 * reindexing pg_index itself, we must not try to update tuples in it.
3845 * pg_index's indexes should always have these flags in their clean state,
3846 * so that won't happen.
3847 */
3848 if (!skipped_constraint)
3849 {
3853 bool index_bad;
3854
3856
3860 elog(ERROR, "cache lookup failed for index %u", indexId);
3862
3863 index_bad = (!indexForm->indisvalid ||
3864 !indexForm->indisready ||
3865 !indexForm->indislive);
3866 if (index_bad ||
3867 (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain))
3868 {
3869 if (!indexInfo->ii_BrokenHotChain)
3870 indexForm->indcheckxmin = false;
3871 else if (index_bad)
3872 indexForm->indcheckxmin = true;
3873 indexForm->indisvalid = true;
3874 indexForm->indisready = true;
3875 indexForm->indislive = true;
3877
3878 /*
3879 * Invalidate the relcache for the table, so that after we commit
3880 * all sessions will refresh the table's index list. This ensures
3881 * that if anyone misses seeing the pg_index row during this
3882 * update, they'll refresh their list before attempting any update
3883 * on the table.
3884 */
3885 CacheInvalidateRelcache(heapRelation);
3886 }
3887
3889 }
3890
3891 /* Log what we did */
3892 if ((params->options & REINDEXOPT_VERBOSE) != 0)
3893 ereport(INFO,
3894 (errmsg("index \"%s\" was reindexed",
3896 errdetail_internal("%s",
3897 pg_rusage_show(&ru0))));
3898
3899 /* Roll back any GUC changes executed by index functions */
3900 AtEOXact_GUC(false, save_nestlevel);
3901
3902 /* Restore userid and security context */
3903 SetUserIdAndSecContext(save_userid, save_sec_context);
3904
3905 /* Close rels, but keep locks */
3907 table_close(heapRelation, NoLock);
3908
3909 if (progress)
3911}
3912
3913/*
3914 * reindex_relation - This routine is used to recreate all indexes
3915 * of a relation (and optionally its toast relation too, if any).
3916 *
3917 * "flags" is a bitmask that can include any combination of these bits:
3918 *
3919 * REINDEX_REL_PROCESS_TOAST: if true, process the toast table too (if any).
3920 *
3921 * REINDEX_REL_SUPPRESS_INDEX_USE: if true, the relation was just completely
3922 * rebuilt by an operation such as VACUUM FULL or CLUSTER, and therefore its
3923 * indexes are inconsistent with it. This makes things tricky if the relation
3924 * is a system catalog that we might consult during the reindexing. To deal
3925 * with that case, we mark all of the indexes as pending rebuild so that they
3926 * won't be trusted until rebuilt. The caller is required to call us *without*
3927 * having made the rebuilt table visible by doing CommandCounterIncrement;
3928 * we'll do CCI after having collected the index list. (This way we can still
3929 * use catalog indexes while collecting the list.)
3930 *
3931 * REINDEX_REL_CHECK_CONSTRAINTS: if true, recheck unique and exclusion
3932 * constraint conditions, else don't. To avoid deadlocks, VACUUM FULL or
3933 * CLUSTER on a system catalog must omit this flag. REINDEX should be used to
3934 * rebuild an index if constraint inconsistency is suspected. For optimal
3935 * performance, other callers should include the flag only after transforming
3936 * the data in a manner that risks a change in constraint validity.
3937 *
3938 * REINDEX_REL_FORCE_INDEXES_UNLOGGED: if true, set the persistence of the
3939 * rebuilt indexes to unlogged.
3940 *
3941 * REINDEX_REL_FORCE_INDEXES_PERMANENT: if true, set the persistence of the
3942 * rebuilt indexes to permanent.
3943 *
3944 * Returns true if any indexes were rebuilt (including toast table's index
3945 * when relevant). Note that a CommandCounterIncrement will occur after each
3946 * index rebuild.
3947 */
3948bool
3949reindex_relation(const ReindexStmt *stmt, Oid relid, int flags,
3950 const ReindexParams *params)
3951{
3952 Relation rel;
3954 List *indexIds;
3955 char persistence;
3956 bool result = false;
3958 int i;
3959
3960 /*
3961 * Open and lock the relation. ShareLock is sufficient since we only need
3962 * to prevent schema and data changes in it. The lock level used here
3963 * should match ReindexTable().
3964 */
3965 if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3966 rel = try_table_open(relid, ShareLock);
3967 else
3968 rel = table_open(relid, ShareLock);
3969
3970 /* if relation is gone, leave */
3971 if (!rel)
3972 return false;
3973
3974 /*
3975 * Partitioned tables should never get processed here, as they have no
3976 * physical storage.
3977 */
3978 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3979 elog(ERROR, "cannot reindex partitioned table \"%s.%s\"",
3982
3983 toast_relid = rel->rd_rel->reltoastrelid;
3984
3985 /*
3986 * Get the list of index OIDs for this relation. (We trust the relcache
3987 * to get this with a sequential scan if ignoring system indexes.)
3988 */
3990
3992 {
3993 /* Suppress use of all the indexes until they are rebuilt */
3995
3996 /*
3997 * Make the new heap contents visible --- now things might be
3998 * inconsistent!
3999 */
4001 }
4002
4003 /*
4004 * Reindex the toast table, if any, before the main table.
4005 *
4006 * This helps in cases where a corruption in the toast table's index would
4007 * otherwise error and stop REINDEX TABLE command when it tries to fetch a
4008 * toasted datum. This way. the toast table's index is rebuilt and fixed
4009 * before it is used for reindexing the main table.
4010 *
4011 * It is critical to call reindex_relation() *after* the call to
4012 * RelationGetIndexList() returning the list of indexes on the relation,
4013 * because reindex_relation() will call CommandCounterIncrement() after
4014 * every reindex_index(). See REINDEX_REL_SUPPRESS_INDEX_USE for more
4015 * details.
4016 */
4018 {
4019 /*
4020 * Note that this should fail if the toast relation is missing, so
4021 * reset REINDEXOPT_MISSING_OK. Even if a new tablespace is set for
4022 * the parent relation, the indexes on its toast table are not moved.
4023 * This rule is enforced by setting tablespaceOid to InvalidOid.
4024 */
4025 ReindexParams newparams = *params;
4026
4028 newparams.tablespaceOid = InvalidOid;
4029 result |= reindex_relation(stmt, toast_relid, flags, &newparams);
4030 }
4031
4032 /*
4033 * Compute persistence of indexes: same as that of owning rel, unless
4034 * caller specified otherwise.
4035 */
4037 persistence = RELPERSISTENCE_UNLOGGED;
4038 else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT)
4039 persistence = RELPERSISTENCE_PERMANENT;
4040 else
4041 persistence = rel->rd_rel->relpersistence;
4042
4043 /* Reindex all the indexes. */
4044 i = 1;
4045 foreach(indexId, indexIds)
4046 {
4047 Oid indexOid = lfirst_oid(indexId);
4049
4050 /*
4051 * Skip any invalid indexes on a TOAST table. These can only be
4052 * duplicate leftovers from a failed REINDEX CONCURRENTLY, and if
4053 * rebuilt it would not be possible to drop them anymore.
4054 */
4056 !get_index_isvalid(indexOid))
4057 {
4060 errmsg("cannot reindex invalid index \"%s.%s\" on TOAST table, skipping",
4062 get_rel_name(indexOid))));
4063
4064 /*
4065 * Remove this invalid toast index from the reindex pending list,
4066 * as it is skipped here due to the hard failure that would happen
4067 * in reindex_index(), should we try to process it.
4068 */
4070 RemoveReindexPending(indexOid);
4071 continue;
4072 }
4073
4074 reindex_index(stmt, indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
4075 persistence, params);
4076
4078
4079 /* Index should no longer be in the pending list */
4080 Assert(!ReindexIsProcessingIndex(indexOid));
4081
4082 /* Set index rebuild count */
4084 i);
4085 i++;
4086 }
4087
4088 /*
4089 * Close rel, but continue to hold the lock.
4090 */
4091 table_close(rel, NoLock);
4092
4093 result |= (indexIds != NIL);
4094
4095 return result;
4096}
4097
4098
4099/* ----------------------------------------------------------------
4100 * System index reindexing support
4101 *
4102 * When we are busy reindexing a system index, this code provides support
4103 * for preventing catalog lookups from using that index. We also make use
4104 * of this to catch attempted uses of user indexes during reindexing of
4105 * those indexes. This information is propagated to parallel workers;
4106 * attempting to change it during a parallel operation is not permitted.
4107 * ----------------------------------------------------------------
4108 */
4109
4113static int reindexingNestLevel = 0;
4114
4115/*
4116 * ReindexIsProcessingHeap
4117 * True if heap specified by OID is currently being reindexed.
4118 */
4119bool
4121{
4122 return heapOid == currentlyReindexedHeap;
4123}
4124
4125/*
4126 * ReindexIsCurrentlyProcessingIndex
4127 * True if index specified by OID is currently being reindexed.
4128 */
4129static bool
4131{
4132 return indexOid == currentlyReindexedIndex;
4133}
4134
4135/*
4136 * ReindexIsProcessingIndex
4137 * True if index specified by OID is currently being reindexed,
4138 * or should be treated as invalid because it is awaiting reindex.
4139 */
4140bool
4142{
4143 return indexOid == currentlyReindexedIndex ||
4145}
4146
4147/*
4148 * SetReindexProcessing
4149 * Set flag that specified heap/index are being reindexed.
4150 */
4151static void
4152SetReindexProcessing(Oid heapOid, Oid indexOid)
4153{
4154 Assert(OidIsValid(heapOid) && OidIsValid(indexOid));
4155 /* Reindexing is not re-entrant. */
4157 elog(ERROR, "cannot reindex while reindexing");
4158 currentlyReindexedHeap = heapOid;
4159 currentlyReindexedIndex = indexOid;
4160 /* Index is no longer "pending" reindex. */
4161 RemoveReindexPending(indexOid);
4162 /* This may have been set already, but in case it isn't, do so now. */
4164}
4165
4166/*
4167 * ResetReindexProcessing
4168 * Unset reindexing status.
4169 */
4170static void
4172{
4175 /* reindexingNestLevel remains set till end of (sub)transaction */
4176}
4177
4178/*
4179 * SetReindexPending
4180 * Mark the given indexes as pending reindex.
4181 *
4182 * NB: we assume that the current memory context stays valid throughout.
4183 */
4184static void
4186{
4187 /* Reindexing is not re-entrant. */
4189 elog(ERROR, "cannot reindex while reindexing");
4190 if (IsInParallelMode())
4191 elog(ERROR, "cannot modify reindex state during a parallel operation");
4194}
4195
4196/*
4197 * RemoveReindexPending
4198 * Remove the given index from the pending list.
4199 */
4200static void
4202{
4203 if (IsInParallelMode())
4204 elog(ERROR, "cannot modify reindex state during a parallel operation");
4206 indexOid);
4207}
4208
4209/*
4210 * ResetReindexState
4211 * Clear all reindexing state during (sub)transaction abort.
4212 */
4213void
4214ResetReindexState(int nestLevel)
4215{
4216 /*
4217 * Because reindexing is not re-entrant, we don't need to cope with nested
4218 * reindexing states. We just need to avoid messing up the outer-level
4219 * state in case a subtransaction fails within a REINDEX. So checking the
4220 * current nest level against that of the reindex operation is sufficient.
4221 */
4222 if (reindexingNestLevel >= nestLevel)
4223 {
4226
4227 /*
4228 * We needn't try to release the contents of pendingReindexedIndexes;
4229 * that list should be in a transaction-lifespan context, so it will
4230 * go away automatically.
4231 */
4233
4235 }
4236}
4237
4238/*
4239 * EstimateReindexStateSpace
4240 * Estimate space needed to pass reindex state to parallel workers.
4241 */
4242Size
4248
4249/*
4250 * SerializeReindexState
4251 * Serialize reindex state for parallel workers.
4252 */
4253void
4255{
4257 int c = 0;
4258 ListCell *lc;
4259
4260 sistate->currentlyReindexedHeap = currentlyReindexedHeap;
4261 sistate->currentlyReindexedIndex = currentlyReindexedIndex;
4262 sistate->numPendingReindexedIndexes = list_length(pendingReindexedIndexes);
4263 foreach(lc, pendingReindexedIndexes)
4264 sistate->pendingReindexedIndexes[c++] = lfirst_oid(lc);
4265}
4266
4267/*
4268 * RestoreReindexState
4269 * Restore reindex state in a parallel worker.
4270 */
4271void
4273{
4275 int c = 0;
4276 MemoryContext oldcontext;
4277
4278 currentlyReindexedHeap = sistate->currentlyReindexedHeap;
4279 currentlyReindexedIndex = sistate->currentlyReindexedIndex;
4280
4283 for (c = 0; c < sistate->numPendingReindexedIndexes; ++c)
4286 sistate->pendingReindexedIndexes[c]);
4287 MemoryContextSwitchTo(oldcontext);
4288
4289 /* Note the worker has its own transaction nesting level */
4291}
const IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition amapi.c:69
StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok)
Definition amapi.c:161
int16 AttrNumber
Definition attnum.h:21
#define AttrNumberGetAttrOffset(attNum)
Definition attnum.h:51
#define InvalidAttrNumber
Definition attnum.h:23
bool AutoVacuumingActive(void)
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
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
uint32 BlockNumber
Definition block.h:31
static Datum values[MAXATTR]
Definition bootstrap.c:188
void index_register(Oid heap, Oid ind, const IndexInfo *indexInfo)
Definition bootstrap.c:1123
#define RelationGetNumberOfBlocks(reln)
Definition bufmgr.h:307
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:837
uint16 bits16
Definition c.h:626
#define Assert(condition)
Definition c.h:945
int64_t int64
Definition c.h:615
TransactionId MultiXactId
Definition c.h:748
#define FLEXIBLE_ARRAY_MEMBER
Definition c.h:552
int16_t int16
Definition c.h:613
int32_t int32
Definition c.h:614
uint16_t uint16
Definition c.h:617
float float4
Definition c.h:715
#define MemSet(start, val, len)
Definition c.h:1109
uint32 TransactionId
Definition c.h:738
#define OidIsValid(objectId)
Definition c.h:860
size_t Size
Definition c.h:691
bool IsToastNamespace(Oid namespaceId)
Definition catalog.c:261
bool IsSystemRelation(Relation relation)
Definition catalog.c:74
RelFileNumber GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
Definition catalog.c:557
bool IsCatalogRelation(Relation relation)
Definition catalog.c:104
@ COMPARE_EQ
Definition cmptype.h:36
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
@ DEPENDENCY_AUTO
Definition dependency.h:34
@ DEPENDENCY_INTERNAL
Definition dependency.h:35
@ DEPENDENCY_PARTITION_PRI
Definition dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition dependency.h:37
@ DEPENDENCY_NORMAL
Definition dependency.h:33
int errcode(int sqlerrcode)
Definition elog.c:874
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:36
#define DEBUG2
Definition elog.h:29
#define DEBUG1
Definition elog.h:30
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define NOTICE
Definition elog.h:35
#define INFO
Definition elog.h:34
#define ereport(elevel,...)
Definition elog.h:150
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, const Node *parsetree)
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition execExpr.c:826
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition execExpr.c:872
void check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo, const ItemPointerData *tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
void FreeExecutorState(EState *estate)
Definition execUtils.c:197
EState * CreateExecutorState(void)
Definition execUtils.c:90
#define GetPerTupleExprContext(estate)
Definition executor.h:660
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition executor.h:522
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:439
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define palloc0_array(type, count)
Definition fe_memutils.h:77
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
void systable_inplace_update_cancel(void *state)
Definition genam.c:903
void systable_inplace_update_begin(Relation relation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, const ScanKeyData *key, HeapTuple *oldtupcopy, void **state)
Definition genam.c:808
void systable_inplace_update_finish(void *state, HeapTuple tuple)
Definition genam.c:884
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
bool IsBinaryUpgrade
Definition globals.c:121
int maintenance_work_mem
Definition globals.c:133
int NewGUCNestLevel(void)
Definition guc.c:2142
void RestrictSearchPath(void)
Definition guc.c:2153
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition guc.c:2169
void DeleteRelationTuple(Oid relid)
Definition heap.c:1576
void DeleteAttributeTuples(Oid relid)
Definition heap.c:1605
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition heap.c:3495
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
Definition heap.c:544
void CopyStatistics(Oid fromrelid, Oid torelid)
Definition heap.c:3442
void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
Definition heap.c:910
void InsertPgAttributeTuples(Relation pg_attribute_rel, TupleDesc tupdesc, Oid new_rel_oid, const FormExtraData_pg_attribute tupdesc_extra[], CatalogIndexState indstate)
Definition heap.c:717
Relation heap_create(const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, RelFileNumber relfilenumber, Oid accessmtd, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods, TransactionId *relfrozenxid, MultiXactId *relminmxid, bool create_storage)
Definition heap.c:285
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1130
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:698
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1384
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define stmt
bool ReindexIsProcessingIndex(Oid indexOid)
Definition index.c:4141
static bool validate_index_callback(ItemPointer itemptr, void *opaque)
Definition index.c:3484
void validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
Definition index.c:3351
void index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode)
Definition index.c:2123
void ResetReindexState(int nestLevel)
Definition index.c:4214
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition index.c:3584
static int reindexingNestLevel
Definition index.c:4113
void index_concurrently_set_dead(Oid heapId, Oid indexId)
Definition index.c:1824
Oid index_create(Relation heapRelation, const char *indexRelationName, Oid indexRelationId, Oid parentIndexRelid, Oid parentConstraintId, RelFileNumber relFileNumber, IndexInfo *indexInfo, const List *indexColNames, Oid accessMethodId, Oid tableSpaceId, const Oid *collationIds, const Oid *opclassIds, const Datum *opclassOptions, const int16 *coloptions, const NullableDatum *stattargets, Datum reloptions, bits16 flags, bits16 constr_flags, bool allow_system_table_mods, bool is_internal, Oid *constraintId)
Definition index.c:727
static Oid currentlyReindexedHeap
Definition index.c:4110
static void ResetReindexProcessing(void)
Definition index.c:4171
void index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
Definition index.c:1553
static void RemoveReindexPending(Oid indexOid)
Definition index.c:4201
static List * pendingReindexedIndexes
Definition index.c:4112
void index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
Definition index.c:3504
bool CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2, const Oid *collations1, const Oid *collations2, const Oid *opfamilies1, const Oid *opfamilies2, const AttrMap *attmap)
Definition index.c:2538
RelFileNumber binary_upgrade_next_index_pg_class_relfilenumber
Definition index.c:87
IndexInfo * BuildDummyIndexInfo(Relation index)
Definition index.c:2489
bool reindex_relation(const ReindexStmt *stmt, Oid relid, int flags, const ReindexParams *params)
Definition index.c:3949
void SerializeReindexState(Size maxsize, char *start_address)
Definition index.c:4254
static void index_update_stats(Relation rel, bool hasindex, double reltuples)
Definition index.c:2810
IndexInfo * BuildIndexInfo(Relation index)
Definition index.c:2429
static bool relationHasPrimaryKey(Relation rel)
Definition index.c:149
static void SetReindexProcessing(Oid heapOid, Oid indexOid)
Definition index.c:4152
static void IndexCheckExclusion(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo)
Definition index.c:3196
static void InitializeAttributeOids(Relation indexRelation, int numatts, Oid indexoid)
Definition index.c:495
Oid index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, Oid tablespaceOid, const char *newName)
Definition index.c:1301
Oid binary_upgrade_next_index_pg_class_oid
Definition index.c:86
static void AppendAttributeTuples(Relation indexRelation, const Datum *attopts, const NullableDatum *stattargets)
Definition index.c:513
void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
Definition index.c:2670
void index_check_primary_key(Relation heapRel, const IndexInfo *indexInfo, bool is_alter_table, const IndexStmt *stmt)
Definition index.c:203
bool ReindexIsProcessingHeap(Oid heapOid)
Definition index.c:4120
static bool ReindexIsCurrentlyProcessingIndex(Oid indexOid)
Definition index.c:4130
void RestoreReindexState(const void *reindexstate)
Definition index.c:4272
static TupleDesc ConstructTupleDescriptor(Relation heapRelation, const IndexInfo *indexInfo, const List *indexColNames, Oid accessMethodId, const Oid *collationIds, const Oid *opclassIds)
Definition index.c:282
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isreindex, bool parallel)
Definition index.c:3003
ObjectAddress index_constraint_create(Relation heapRelation, Oid indexRelationId, Oid parentConstraintId, const IndexInfo *indexInfo, const char *constraintName, char constraintType, bits16 constr_flags, bool allow_system_table_mods, bool is_internal)
Definition index.c:1886
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition index.c:2731
static void SetReindexPending(List *indexes)
Definition index.c:4185
void index_concurrently_build(Oid heapRelationId, Oid indexRelationId)
Definition index.c:1486
static void UpdateIndexRelation(Oid indexoid, Oid heapoid, Oid parentIndexId, const IndexInfo *indexInfo, const Oid *collationOids, const Oid *opclassOids, const int16 *coloptions, bool primary, bool isexclusion, bool immediate, bool isvalid, bool isready)
Definition index.c:564
static Oid currentlyReindexedIndex
Definition index.c:4111
Size EstimateReindexStateSpace(void)
Definition index.c:4243
void reindex_index(const ReindexStmt *stmt, Oid indexId, bool skip_constraint_checks, char persistence, const ReindexParams *params)
Definition index.c:3609
#define INDEX_CREATE_IS_PRIMARY
Definition index.h:67
#define INDEX_CREATE_IF_NOT_EXISTS
Definition index.h:71
#define REINDEX_REL_PROCESS_TOAST
Definition index.h:165
#define INDEX_CREATE_PARTITIONED
Definition index.h:72
#define REINDEXOPT_MISSING_OK
Definition index.h:49
#define INDEX_CREATE_INVALID
Definition index.h:73
#define INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS
Definition index.h:102
#define INDEX_CREATE_ADD_CONSTRAINT
Definition index.h:68
#define INDEX_CREATE_SKIP_BUILD
Definition index.h:69
#define INDEX_CONSTR_CREATE_UPDATE_INDEX
Definition index.h:100
#define REINDEX_REL_FORCE_INDEXES_UNLOGGED
Definition index.h:168
#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS
Definition index.h:101
static int64 itemptr_encode(const ItemPointerData *itemptr)
Definition index.h:196
#define INDEX_CONSTR_CREATE_DEFERRABLE
Definition index.h:98
#define REINDEXOPT_REPORT_PROGRESS
Definition index.h:48
#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY
Definition index.h:97
#define REINDEX_REL_SUPPRESS_INDEX_USE
Definition index.h:166
IndexStateFlagsAction
Definition index.h:31
@ INDEX_CREATE_SET_VALID
Definition index.h:33
@ INDEX_DROP_CLEAR_VALID
Definition index.h:34
@ INDEX_DROP_SET_DEAD
Definition index.h:35
@ INDEX_CREATE_SET_READY
Definition index.h:32
#define REINDEX_REL_FORCE_INDEXES_PERMANENT
Definition index.h:169
#define INDEX_CONSTR_CREATE_INIT_DEFERRED
Definition index.h:99
#define INDEX_CREATE_CONCURRENT
Definition index.h:70
#define REINDEXOPT_VERBOSE
Definition index.h:47
#define REINDEX_REL_CHECK_CONSTRAINTS
Definition index.h:167
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition indexam.c:1048
IndexBulkDeleteResult * index_bulk_delete(IndexVacuumInfo *info, IndexBulkDeleteResult *istat, IndexBulkDeleteCallback callback, void *callback_state)
Definition indexam.c:805
void index_insert_cleanup(Relation indexRelation, IndexInfo *indexInfo)
Definition indexam.c:241
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:177
Relation try_index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:152
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:133
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition indexing.c:61
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition indexing.c:43
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
int2vector * buildint2vector(const int16 *int2s, int n)
Definition int.c:114
void CacheInvalidateRelcache(Relation relation)
Definition inval.c:1635
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition inval.c:1669
invalidindex index d is invalid
Definition isn.c:138
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_delete_oid(List *list, Oid datum)
Definition list.c:910
List * list_copy(const List *oldlist)
Definition list.c:1573
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
void list_free(List *list)
Definition list.c:1546
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition lmgr.c:391
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
void LockRelation(Relation relation, LOCKMODE lockmode)
Definition lmgr.c:246
void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress)
Definition lmgr.c:989
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition lmgr.c:404
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
#define AccessExclusiveLock
Definition lockdefs.h:43
#define ShareUpdateExclusiveLock
Definition lockdefs.h:39
#define ShareLock
Definition lockdefs.h:40
#define RowExclusiveLock
Definition lockdefs.h:38
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition locktag.h:81
char * get_rel_name(Oid relid)
Definition lsyscache.c:2148
bool get_rel_relispartition(Oid relid)
Definition lsyscache.c:2247
char get_rel_persistence(Oid relid)
Definition lsyscache.c:2298
bool get_index_isvalid(Oid index_oid)
Definition lsyscache.c:3800
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1089
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2172
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1505
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition lsyscache.c:170
bool get_collation_isdeterministic(Oid colloid)
Definition lsyscache.c:1200
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:3054
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2105
Expr * make_ands_explicit(List *andclauses)
Definition makefuncs.c:799
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
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
void pfree(void *pointer)
Definition mcxt.c:1616
MemoryContext TopMemoryContext
Definition mcxt.c:166
#define IsBootstrapProcessingMode()
Definition miscadmin.h:477
#define SECURITY_RESTRICTED_OPERATION
Definition miscadmin.h:319
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
#define IsNormalProcessingMode()
Definition miscadmin.h:479
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition miscinit.c:613
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition miscinit.c:620
#define InvalidMultiXactId
Definition multixact.h:25
void namestrcpy(Name name, const char *str)
Definition name.c:233
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
#define makeNode(_type_)
Definition nodes.h:161
static char * errmsg
#define InvokeObjectPostAlterHookArg(classId, objectId, subId, auxiliaryId, is_internal)
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
oidvector * buildoidvector(const Oid *oids, int n)
Definition oid.c:87
char * nodeToString(const void *obj)
Definition outfuncs.c:811
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
List * SystemFuncName(char *name)
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
FormData_pg_attribute
#define ATTRIBUTE_FIXED_PART_SIZE
int16 attnum
FormData_pg_attribute * Form_pg_attribute
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
#define INDEX_MAX_KEYS
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isEnforced, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int16 conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)
bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, const char *conname)
@ CONSTRAINT_RELATION
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition pg_depend.c:353
long changeDependenciesOf(Oid classId, Oid oldObjectId, Oid newObjectId)
Definition pg_depend.c:567
List * get_index_ref_constraints(Oid indexId)
Definition pg_depend.c:1117
long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition pg_depend.c:623
Oid get_index_constraint(Oid indexId)
Definition pg_depend.c:1061
END_CATALOG_STRUCT typedef FormData_pg_index * Form_pg_index
Definition pg_index.h:74
bool DeleteInheritsTuple(Oid inhrelid, Oid inhparent, bool expect_detach_pending, const char *childname)
void StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber)
#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
static ListCell * list_head(const List *l)
Definition pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:343
#define linitial_oid(l)
Definition pg_list.h:180
#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
END_CATALOG_STRUCT typedef FormData_pg_trigger * Form_pg_trigger
Definition pg_trigger.h:84
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
static int progress
Definition pgbench.c:262
void pgstat_copy_relation_stats(Relation dst, Relation src)
void pgstat_drop_relation(Relation rel)
int plan_create_index_workers(Oid tableOid, Oid indexOid)
Definition planner.c:7021
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
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 Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid
unsigned int Oid
void TransferPredicateLocksToHeapRelation(Relation relation)
Definition predicate.c:3132
char * c
static int fb(int x)
#define PROGRESS_CREATEIDX_PHASE_BUILD
Definition progress.h:120
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_TABLESCAN
Definition progress.h:124
#define PROGRESS_CREATEIDX_ACCESS_METHOD_OID
Definition progress.h:109
#define PROGRESS_CREATEIDX_TUPLES_TOTAL
Definition progress.h:112
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_SORT
Definition progress.h:123
#define PROGRESS_SCAN_BLOCKS_DONE
Definition progress.h:148
#define PROGRESS_CREATEIDX_TUPLES_DONE
Definition progress.h:113
#define PROGRESS_CREATEIDX_SUBPHASE
Definition progress.h:111
#define PROGRESS_REPACK_INDEX_REBUILD_COUNT
Definition progress.h:92
#define PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE
Definition progress.h:132
#define PROGRESS_CREATEIDX_PHASE
Definition progress.h:110
#define PROGRESS_CREATEIDX_COMMAND_REINDEX
Definition progress.h:138
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN
Definition progress.h:122
#define PROGRESS_SCAN_BLOCKS_TOTAL
Definition progress.h:147
#define PROGRESS_CREATEIDX_INDEX_OID
Definition progress.h:108
#define PROGRESS_CREATEIDX_COMMAND
Definition progress.h:107
void * stringToNode(const char *str)
Definition read.c:90
#define RelationGetForm(relation)
Definition rel.h:508
#define RelationGetRelid(relation)
Definition rel.h:514
static SMgrRelation RelationGetSmgr(Relation rel)
Definition rel.h:576
#define RelationGetDescr(relation)
Definition rel.h:540
#define RelationIsMapped(relation)
Definition rel.h:563
#define RelationGetRelationName(relation)
Definition rel.h:548
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:667
#define RelationIsValid(relation)
Definition rel.h:489
#define RelationGetNamespace(relation)
Definition rel.h:555
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:533
List * RelationGetIndexList(Relation relation)
Definition relcache.c:4826
List * RelationGetDummyIndexExpressions(Relation relation)
Definition relcache.c:5146
void RelationInitIndexAccessInfo(Relation relation)
Definition relcache.c:1435
List * RelationGetIndexPredicate(Relation relation)
Definition relcache.c:5200
void RelationSetNewRelfilenumber(Relation relation, char persistence)
Definition relcache.c:3764
void RelationForgetRelation(Oid rid)
Definition relcache.c:2882
List * RelationGetIndexExpressions(Relation relation)
Definition relcache.c:5087
void RelationAssumeNewRelfilelocator(Relation relation)
Definition relcache.c:3967
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition relcache.c:5643
Oid RelFileNumber
Definition relpath.h:25
@ INIT_FORKNUM
Definition relpath.h:61
#define InvalidRelFileNumber
Definition relpath.h:26
#define RelFileNumberIsValid(relnumber)
Definition relpath.h:27
Node * map_variable_attnos(Node *node, int target_varno, int sublevels_up, const AttrMap *attno_map, Oid to_rowtype, bool *found_whole_row)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
@ ForwardScanDirection
Definition sdir.h:28
Size mul_size(Size s1, Size s2)
Definition shmem.c:500
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition smgr.c:481
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition smgr.c:462
Snapshot GetTransactionSnapshot(void)
Definition snapmgr.c:272
Snapshot GetLatestSnapshot(void)
Definition snapmgr.c:354
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
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:47
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition storage.c:187
void RelationDropStorage(Relation rel)
Definition storage.c:207
#define BTEqualStrategyNumber
Definition stratnum.h:31
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
MemoryContext ecxt_per_tuple_memory
Definition execnodes.h:292
TupleTableSlot * ecxt_scantuple
Definition execnodes.h:284
ItemPointerData t_self
Definition htup.h:65
ambuildempty_function ambuildempty
Definition amapi.h:296
ambuild_function ambuild
Definition amapi.h:295
bool amsummarizing
Definition amapi.h:282
bool amcanbuildparallel
Definition amapi.h:276
double heap_tuples
Definition genam.h:40
double index_tuples
Definition genam.h:41
bool ii_Unique
Definition execnodes.h:211
uint16 * ii_ExclusionStrats
Definition execnodes.h:203
bool ii_BrokenHotChain
Definition execnodes.h:223
int ii_NumIndexAttrs
Definition execnodes.h:178
Oid * ii_UniqueOps
Definition execnodes.h:206
ExprState * ii_PredicateState
Definition execnodes.h:196
Oid * ii_ExclusionOps
Definition execnodes.h:199
bool ii_NullsNotDistinct
Definition execnodes.h:213
int ii_ParallelWorkers
Definition execnodes.h:229
bool ii_Concurrent
Definition execnodes.h:221
uint16 * ii_UniqueStrats
Definition execnodes.h:208
int ii_NumIndexKeyAttrs
Definition execnodes.h:180
List * ii_ExpressionsState
Definition execnodes.h:191
List * ii_Expressions
Definition execnodes.h:189
Oid * ii_ExclusionProcs
Definition execnodes.h:201
AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS]
Definition execnodes.h:186
Oid * ii_UniqueProcs
Definition execnodes.h:207
bool ii_ReadyForInserts
Definition execnodes.h:215
List * ii_Predicate
Definition execnodes.h:194
Definition pg_list.h:54
Oid relId
Definition rel.h:40
Oid dbId
Definition rel.h:41
Definition nodes.h:135
Oid tablespaceOid
Definition index.h:42
bits32 options
Definition index.h:41
const struct IndexAmRoutine * rd_indam
Definition rel.h:206
TupleDesc rd_att
Definition rel.h:112
Form_pg_index rd_index
Definition rel.h:192
MemoryContext rd_indexcxt
Definition rel.h:204
RelFileLocator rd_locator
Definition rel.h:57
bytea * rd_options
Definition rel.h:175
Oid * rd_indcollation
Definition rel.h:217
Form_pg_class rd_rel
Definition rel.h:111
Oid currentlyReindexedIndex
Definition index.c:97
int numPendingReindexedIndexes
Definition index.c:98
ItemPointerData tts_tid
Definition tuptable.h:142
Definition type.h:96
Definition c.h:817
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:230
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:625
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
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
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition tableam.c:92
static void table_endscan(TableScanDesc scan)
Definition tableam.h:1004
static void table_index_validate_scan(Relation table_rel, Relation index_rel, IndexInfo *index_info, Snapshot snapshot, ValidateIndexState *state)
Definition tableam.h:1829
static TableScanDesc table_beginscan_strat(Relation rel, Snapshot snapshot, int nkeys, ScanKeyData *key, bool allow_strat, bool allow_sync)
Definition tableam.h:920
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition tableam.h:1039
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition tablecmds.c:4447
bool CheckRelationTableSpaceMove(Relation rel, Oid newTableSpaceId)
Definition tablecmds.c:3724
void SetRelationHasSubclass(Oid relationId, bool relhassubclass)
Definition tablecmds.c:3678
void SetRelationTableSpace(Relation rel, Oid newTableSpaceId, RelFileNumber newRelFilenumber)
Definition tablecmds.c:3781
#define InvalidCompressionMethod
#define InvalidTransactionId
Definition transam.h:31
ObjectAddress CreateTrigger(const CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition)
Definition trigger.c:162
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:508
void populate_compact_attribute(TupleDesc tupdesc, int attnum)
Definition tupdesc.c:100
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
void tuplesort_performsort(Tuplesortstate *state)
Definition tuplesort.c:1259
void tuplesort_end(Tuplesortstate *state)
Definition tuplesort.c:847
#define TUPLESORT_NONE
Definition tuplesort.h:67
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, SortCoordinate coordinate, int sortopt)
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition tuptable.h:438
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition tuptable.h:417
void visibilitymap_count(Relation rel, BlockNumber *all_visible, BlockNumber *all_frozen)
const char * description
int GetCurrentTransactionNestLevel(void)
Definition xact.c:931
void CommandCounterIncrement(void)
Definition xact.c:1102
TransactionId GetTopTransactionIdIfAny(void)
Definition xact.c:443
void StartTransactionCommand(void)
Definition xact.c:3081
bool IsInParallelMode(void)
Definition xact.c:1091
void CommitTransactionCommand(void)
Definition xact.c:3179