PostgreSQL Source Code  git master
index.h File Reference
Include dependency graph for index.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define DEFAULT_INDEX_TYPE   "btree"
 
#define INDEX_CREATE_IS_PRIMARY   (1 << 0)
 
#define INDEX_CREATE_ADD_CONSTRAINT   (1 << 1)
 
#define INDEX_CREATE_SKIP_BUILD   (1 << 2)
 
#define INDEX_CREATE_CONCURRENT   (1 << 3)
 
#define INDEX_CREATE_IF_NOT_EXISTS   (1 << 4)
 
#define INDEX_CREATE_PARTITIONED   (1 << 5)
 
#define INDEX_CREATE_INVALID   (1 << 6)
 
#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY   (1 << 0)
 
#define INDEX_CONSTR_CREATE_DEFERRABLE   (1 << 1)
 
#define INDEX_CONSTR_CREATE_INIT_DEFERRED   (1 << 2)
 
#define INDEX_CONSTR_CREATE_UPDATE_INDEX   (1 << 3)
 
#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS   (1 << 4)
 
#define REINDEX_REL_PROCESS_TOAST   0x01
 
#define REINDEX_REL_SUPPRESS_INDEX_USE   0x02
 
#define REINDEX_REL_CHECK_CONSTRAINTS   0x04
 
#define REINDEX_REL_FORCE_INDEXES_UNLOGGED   0x08
 
#define REINDEX_REL_FORCE_INDEXES_PERMANENT   0x10
 

Typedefs

typedef void(* IndexBuildCallback) (Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
 

Enumerations

enum  IndexStateFlagsAction { INDEX_CREATE_SET_READY, INDEX_CREATE_SET_VALID, INDEX_DROP_CLEAR_VALID, INDEX_DROP_SET_DEAD }
 

Functions

void index_check_primary_key (Relation heapRel, IndexInfo *indexInfo, bool is_alter_table)
 
Oid index_create (Relation heapRelation, const char *indexRelationName, Oid indexRelationId, Oid parentIndexRelid, Oid parentConstraintId, Oid relFileNode, IndexInfo *indexInfo, List *indexColNames, Oid accessMethodObjectId, Oid tableSpaceId, Oid *collationObjectId, Oid *classObjectId, int16 *coloptions, Datum reloptions, bits16 flags, bits16 constr_flags, bool allow_system_table_mods, bool is_internal, Oid *constraintId)
 
ObjectAddress index_constraint_create (Relation heapRelation, Oid indexRelationId, Oid parentConstraintId, IndexInfo *indexInfo, const char *constraintName, char constraintType, bits16 constr_flags, bool allow_system_table_mods, bool is_internal)
 
void index_drop (Oid indexId, bool concurrent)
 
IndexInfoBuildIndexInfo (Relation index)
 
bool CompareIndexInfo (IndexInfo *info1, IndexInfo *info2, Oid *collations1, Oid *collations2, Oid *opfamilies1, Oid *opfamilies2, AttrNumber *attmap, int maplen)
 
void BuildSpeculativeIndexInfo (Relation index, IndexInfo *ii)
 
void FormIndexDatum (IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
 
void index_build (Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isprimary, bool isreindex, bool parallel)
 
double IndexBuildHeapScan (Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, IndexBuildCallback callback, void *callback_state, HeapScanDesc scan)
 
double IndexBuildHeapRangeScan (Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, bool anyvisible, BlockNumber start_blockno, BlockNumber end_blockno, IndexBuildCallback callback, void *callback_state, HeapScanDesc scan)
 
void validate_index (Oid heapId, Oid indexId, Snapshot snapshot)
 
void index_set_state_flags (Oid indexId, IndexStateFlagsAction action)
 
void reindex_index (Oid indexId, bool skip_constraint_checks, char relpersistence, int options)
 
bool reindex_relation (Oid relid, int flags, int options)
 
bool ReindexIsProcessingHeap (Oid heapOid)
 
bool ReindexIsProcessingIndex (Oid indexOid)
 
Oid IndexGetRelation (Oid indexId, bool missing_ok)
 
Size EstimateReindexStateSpace (void)
 
void SerializeReindexState (Size maxsize, char *start_address)
 
void RestoreReindexState (void *reindexstate)
 
void IndexSetParentIndex (Relation idx, Oid parentOid)
 

Macro Definition Documentation

◆ DEFAULT_INDEX_TYPE

#define DEFAULT_INDEX_TYPE   "btree"

Definition at line 21 of file index.h.

Referenced by transformIndexConstraint().

◆ INDEX_CONSTR_CREATE_DEFERRABLE

#define INDEX_CONSTR_CREATE_DEFERRABLE   (1 << 1)

◆ INDEX_CONSTR_CREATE_INIT_DEFERRED

#define INDEX_CONSTR_CREATE_INIT_DEFERRED   (1 << 2)

Definition at line 75 of file index.h.

Referenced by ATExecAddIndexConstraint(), DefineIndex(), and index_constraint_create().

◆ INDEX_CONSTR_CREATE_MARK_AS_PRIMARY

#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY   (1 << 0)

Definition at line 73 of file index.h.

Referenced by ATExecAddIndexConstraint(), and index_constraint_create().

◆ INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS

#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS   (1 << 4)

Definition at line 77 of file index.h.

Referenced by ATExecAddIndexConstraint(), and index_constraint_create().

◆ INDEX_CONSTR_CREATE_UPDATE_INDEX

#define INDEX_CONSTR_CREATE_UPDATE_INDEX   (1 << 3)

Definition at line 76 of file index.h.

Referenced by ATExecAddIndexConstraint(), and index_constraint_create().

◆ INDEX_CREATE_ADD_CONSTRAINT

#define INDEX_CREATE_ADD_CONSTRAINT   (1 << 1)

Definition at line 46 of file index.h.

Referenced by DefineIndex(), and index_create().

◆ INDEX_CREATE_CONCURRENT

#define INDEX_CREATE_CONCURRENT   (1 << 3)

Definition at line 48 of file index.h.

Referenced by DefineIndex(), and index_create().

◆ INDEX_CREATE_IF_NOT_EXISTS

#define INDEX_CREATE_IF_NOT_EXISTS   (1 << 4)

Definition at line 49 of file index.h.

Referenced by DefineIndex(), and index_create().

◆ INDEX_CREATE_INVALID

#define INDEX_CREATE_INVALID   (1 << 6)

Definition at line 51 of file index.h.

Referenced by DefineIndex(), and index_create().

◆ INDEX_CREATE_IS_PRIMARY

#define INDEX_CREATE_IS_PRIMARY   (1 << 0)

Definition at line 45 of file index.h.

Referenced by create_toast_table(), DefineIndex(), and index_create().

◆ INDEX_CREATE_PARTITIONED

#define INDEX_CREATE_PARTITIONED   (1 << 5)

Definition at line 50 of file index.h.

Referenced by DefineIndex(), and index_create().

◆ INDEX_CREATE_SKIP_BUILD

#define INDEX_CREATE_SKIP_BUILD   (1 << 2)

Definition at line 47 of file index.h.

Referenced by DefineIndex(), and index_create().

◆ REINDEX_REL_CHECK_CONSTRAINTS

#define REINDEX_REL_CHECK_CONSTRAINTS   0x04

Definition at line 141 of file index.h.

Referenced by finish_heap_swap(), reindex_relation(), ReindexMultipleTables(), and ReindexTable().

◆ REINDEX_REL_FORCE_INDEXES_PERMANENT

#define REINDEX_REL_FORCE_INDEXES_PERMANENT   0x10

Definition at line 143 of file index.h.

Referenced by finish_heap_swap(), and reindex_relation().

◆ REINDEX_REL_FORCE_INDEXES_UNLOGGED

#define REINDEX_REL_FORCE_INDEXES_UNLOGGED   0x08

Definition at line 142 of file index.h.

Referenced by finish_heap_swap(), and reindex_relation().

◆ REINDEX_REL_PROCESS_TOAST

#define REINDEX_REL_PROCESS_TOAST   0x01

Definition at line 139 of file index.h.

Referenced by ExecuteTruncate(), reindex_relation(), ReindexMultipleTables(), and ReindexTable().

◆ REINDEX_REL_SUPPRESS_INDEX_USE

#define REINDEX_REL_SUPPRESS_INDEX_USE   0x02

Definition at line 140 of file index.h.

Referenced by finish_heap_swap(), and reindex_relation().

Typedef Documentation

◆ IndexBuildCallback

typedef void(* IndexBuildCallback) (Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)

Definition at line 24 of file index.h.

Enumeration Type Documentation

◆ IndexStateFlagsAction

Enumerator
INDEX_CREATE_SET_READY 
INDEX_CREATE_SET_VALID 
INDEX_DROP_CLEAR_VALID 
INDEX_DROP_SET_DEAD 

Definition at line 32 of file index.h.

Function Documentation

◆ BuildIndexInfo()

IndexInfo* BuildIndexInfo ( Relation  index)

Definition at line 1741 of file index.c.

References CurrentMemoryContext, elog, ERROR, i, IndexInfo::ii_Am, IndexInfo::ii_AmCache, IndexInfo::ii_BrokenHotChain, IndexInfo::ii_Concurrent, IndexInfo::ii_Context, IndexInfo::ii_ExclusionOps, IndexInfo::ii_ExclusionProcs, IndexInfo::ii_ExclusionStrats, IndexInfo::ii_Expressions, IndexInfo::ii_ExpressionsState, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_ParallelWorkers, IndexInfo::ii_Predicate, IndexInfo::ii_PredicateState, IndexInfo::ii_ReadyForInserts, IndexInfo::ii_Unique, IndexInfo::ii_UniqueOps, IndexInfo::ii_UniqueProcs, IndexInfo::ii_UniqueStrats, INDEX_MAX_KEYS, IndexIsReady, makeNode, NIL, RelationData::rd_index, RelationData::rd_rel, RelationGetExclusionInfo(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), and RelationGetRelid.

Referenced by _bt_parallel_scan_and_sort(), ATExecAddIndexConstraint(), ATExecAttachPartitionIdx(), AttachPartitionEnsureIndexes(), brinsummarize(), DefineIndex(), do_analyze_rel(), ExecOpenIndices(), get_actual_variable_range(), reindex_index(), RelationGetIndexAttrBitmap(), RelationTruncateIndexes(), tuplesort_begin_cluster(), unique_key_recheck(), and validate_index().

1742 {
1743  IndexInfo *ii = makeNode(IndexInfo);
1744  Form_pg_index indexStruct = index->rd_index;
1745  int i;
1746  int numKeys;
1747 
1748  /* check the number of keys, and copy attr numbers into the IndexInfo */
1749  numKeys = indexStruct->indnatts;
1750  if (numKeys < 1 || numKeys > INDEX_MAX_KEYS)
1751  elog(ERROR, "invalid indnatts %d for index %u",
1752  numKeys, RelationGetRelid(index));
1753  ii->ii_NumIndexAttrs = numKeys;
1754  for (i = 0; i < numKeys; i++)
1755  ii->ii_KeyAttrNumbers[i] = indexStruct->indkey.values[i];
1756 
1757  /* fetch any expressions needed for expressional indexes */
1759  ii->ii_ExpressionsState = NIL;
1760 
1761  /* fetch index predicate if any */
1763  ii->ii_PredicateState = NULL;
1764 
1765  /* fetch exclusion constraint info if any */
1766  if (indexStruct->indisexclusion)
1767  {
1769  &ii->ii_ExclusionOps,
1770  &ii->ii_ExclusionProcs,
1771  &ii->ii_ExclusionStrats);
1772  }
1773  else
1774  {
1775  ii->ii_ExclusionOps = NULL;
1776  ii->ii_ExclusionProcs = NULL;
1777  ii->ii_ExclusionStrats = NULL;
1778  }
1779 
1780  /* other info */
1781  ii->ii_Unique = indexStruct->indisunique;
1782  ii->ii_ReadyForInserts = IndexIsReady(indexStruct);
1783  /* assume not doing speculative insertion for now */
1784  ii->ii_UniqueOps = NULL;
1785  ii->ii_UniqueProcs = NULL;
1786  ii->ii_UniqueStrats = NULL;
1787 
1788  /* initialize index-build state to default */
1789  ii->ii_Concurrent = false;
1790  ii->ii_BrokenHotChain = false;
1791  ii->ii_ParallelWorkers = 0;
1792 
1793  /* set up for possible use by index AM */
1794  ii->ii_Am = index->rd_rel->relam;
1795  ii->ii_AmCache = NULL;
1797 
1798  return ii;
1799 }
#define NIL
Definition: pg_list.h:69
MemoryContext ii_Context
Definition: execnodes.h:165
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition: relcache.c:5038
uint16 * ii_UniqueStrats
Definition: execnodes.h:157
List * ii_Predicate
Definition: execnodes.h:150
#define IndexIsReady(indexForm)
Definition: pg_index.h:108
ExprState * ii_PredicateState
Definition: execnodes.h:151
Oid * ii_ExclusionProcs
Definition: execnodes.h:153
Form_pg_class rd_rel
Definition: rel.h:114
Oid * ii_UniqueOps
Definition: execnodes.h:155
List * RelationGetIndexPredicate(Relation relation)
Definition: relcache.c:4748
List * ii_ExpressionsState
Definition: execnodes.h:149
Form_pg_index rd_index
Definition: rel.h:159
#define ERROR
Definition: elog.h:43
List * RelationGetIndexExpressions(Relation relation)
Definition: relcache.c:4685
Oid * ii_UniqueProcs
Definition: execnodes.h:156
bool ii_BrokenHotChain
Definition: execnodes.h:161
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
bool ii_ReadyForInserts
Definition: execnodes.h:159
void * ii_AmCache
Definition: execnodes.h:164
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
int ii_NumIndexAttrs
Definition: execnodes.h:146
bool ii_Unique
Definition: execnodes.h:158
#define makeNode(_type_)
Definition: nodes.h:561
List * ii_Expressions
Definition: execnodes.h:148
#define INDEX_MAX_KEYS
int ii_ParallelWorkers
Definition: execnodes.h:162
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:147
bool ii_Concurrent
Definition: execnodes.h:160
Oid * ii_ExclusionOps
Definition: execnodes.h:152
int i
#define elog
Definition: elog.h:219
uint16 * ii_ExclusionStrats
Definition: execnodes.h:154
#define RelationGetRelid(relation)
Definition: rel.h:425
Oid ii_Am
Definition: execnodes.h:163

◆ BuildSpeculativeIndexInfo()

void BuildSpeculativeIndexInfo ( Relation  index,
IndexInfo ii 
)

Definition at line 1923 of file index.c.

References Assert, BTEqualStrategyNumber, BTREE_AM_OID, elog, ERROR, get_opcode(), get_opfamily_member(), i, IndexInfo::ii_Unique, IndexInfo::ii_UniqueOps, IndexInfo::ii_UniqueProcs, IndexInfo::ii_UniqueStrats, OidIsValid, palloc(), RelationData::rd_opcintype, RelationData::rd_opfamily, and RelationData::rd_rel.

Referenced by ExecOpenIndices().

1924 {
1925  int ncols = index->rd_rel->relnatts;
1926  int i;
1927 
1928  /*
1929  * fetch info for checking unique indexes
1930  */
1931  Assert(ii->ii_Unique);
1932 
1933  if (index->rd_rel->relam != BTREE_AM_OID)
1934  elog(ERROR, "unexpected non-btree speculative unique index");
1935 
1936  ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * ncols);
1937  ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * ncols);
1938  ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * ncols);
1939 
1940  /*
1941  * We have to look up the operator's strategy number. This provides a
1942  * cross-check that the operator does match the index.
1943  */
1944  /* We need the func OIDs and strategy numbers too */
1945  for (i = 0; i < ncols; i++)
1946  {
1948  ii->ii_UniqueOps[i] =
1949  get_opfamily_member(index->rd_opfamily[i],
1950  index->rd_opcintype[i],
1951  index->rd_opcintype[i],
1952  ii->ii_UniqueStrats[i]);
1953  if (!OidIsValid(ii->ii_UniqueOps[i]))
1954  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
1955  ii->ii_UniqueStrats[i], index->rd_opcintype[i],
1956  index->rd_opcintype[i], index->rd_opfamily[i]);
1957  ii->ii_UniqueProcs[i] = get_opcode(ii->ii_UniqueOps[i]);
1958  }
1959 }
uint16 * ii_UniqueStrats
Definition: execnodes.h:157
#define BTREE_AM_OID
Definition: pg_am.h:70
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
Oid * ii_UniqueOps
Definition: execnodes.h:155
unsigned short uint16
Definition: c.h:313
#define ERROR
Definition: elog.h:43
Oid * ii_UniqueProcs
Definition: execnodes.h:156
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
Oid * rd_opfamily
Definition: rel.h:182
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1079
bool ii_Unique
Definition: execnodes.h:158
#define Assert(condition)
Definition: c.h:688
void * palloc(Size size)
Definition: mcxt.c:835
int i
#define elog
Definition: elog.h:219
Oid * rd_opcintype
Definition: rel.h:183
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ CompareIndexInfo()

bool CompareIndexInfo ( IndexInfo info1,
IndexInfo info2,
Oid collations1,
Oid collations2,
Oid opfamilies1,
Oid opfamilies2,
AttrNumber attmap,
int  maplen 
)

Definition at line 1812 of file index.c.

References elog, equal(), ERROR, i, IndexInfo::ii_Am, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Expressions, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_Predicate, IndexInfo::ii_Unique, InvalidAttrNumber, InvalidOid, map_variable_attnos(), and NIL.

Referenced by ATExecAttachPartitionIdx(), AttachPartitionEnsureIndexes(), and DefineIndex().

1816 {
1817  int i;
1818 
1819  if (info1->ii_Unique != info2->ii_Unique)
1820  return false;
1821 
1822  /* indexes are only equivalent if they have the same access method */
1823  if (info1->ii_Am != info2->ii_Am)
1824  return false;
1825 
1826  /* and same number of attributes */
1827  if (info1->ii_NumIndexAttrs != info2->ii_NumIndexAttrs)
1828  return false;
1829 
1830  /*
1831  * and columns match through the attribute map (actual attribute numbers
1832  * might differ!) Note that this implies that index columns that are
1833  * expressions appear in the same positions. We will next compare the
1834  * expressions themselves.
1835  */
1836  for (i = 0; i < info1->ii_NumIndexAttrs; i++)
1837  {
1838  if (maplen < info2->ii_KeyAttrNumbers[i])
1839  elog(ERROR, "incorrect attribute map");
1840 
1841  /* ignore expressions at this stage */
1842  if ((info1->ii_KeyAttrNumbers[i] != InvalidAttrNumber) &&
1843  (attmap[info2->ii_KeyAttrNumbers[i] - 1] !=
1844  info1->ii_KeyAttrNumbers[i]))
1845  return false;
1846 
1847  if (collations1[i] != collations2[i])
1848  return false;
1849  if (opfamilies1[i] != opfamilies2[i])
1850  return false;
1851  }
1852 
1853  /*
1854  * For expression indexes: either both are expression indexes, or neither
1855  * is; if they are, make sure the expressions match.
1856  */
1857  if ((info1->ii_Expressions != NIL) != (info2->ii_Expressions != NIL))
1858  return false;
1859  if (info1->ii_Expressions != NIL)
1860  {
1861  bool found_whole_row;
1862  Node *mapped;
1863 
1864  mapped = map_variable_attnos((Node *) info2->ii_Expressions,
1865  1, 0, attmap, maplen,
1866  InvalidOid, &found_whole_row);
1867  if (found_whole_row)
1868  {
1869  /*
1870  * we could throw an error here, but seems out of scope for this
1871  * routine.
1872  */
1873  return false;
1874  }
1875 
1876  if (!equal(info1->ii_Expressions, mapped))
1877  return false;
1878  }
1879 
1880  /* Partial index predicates must be identical, if they exist */
1881  if ((info1->ii_Predicate == NULL) != (info2->ii_Predicate == NULL))
1882  return false;
1883  if (info1->ii_Predicate != NULL)
1884  {
1885  bool found_whole_row;
1886  Node *mapped;
1887 
1888  mapped = map_variable_attnos((Node *) info2->ii_Predicate,
1889  1, 0, attmap, maplen,
1890  InvalidOid, &found_whole_row);
1891  if (found_whole_row)
1892  {
1893  /*
1894  * we could throw an error here, but seems out of scope for this
1895  * routine.
1896  */
1897  return false;
1898  }
1899  if (!equal(info1->ii_Predicate, mapped))
1900  return false;
1901  }
1902 
1903  /* No support currently for comparing exclusion indexes. */
1904  if (info1->ii_ExclusionOps != NULL || info2->ii_ExclusionOps != NULL)
1905  return false;
1906 
1907  return true;
1908 }
#define NIL
Definition: pg_list.h:69
List * ii_Predicate
Definition: execnodes.h:150
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2991
Definition: nodes.h:513
#define ERROR
Definition: elog.h:43
Node * map_variable_attnos(Node *node, int target_varno, int sublevels_up, const AttrNumber *attno_map, int map_length, Oid to_rowtype, bool *found_whole_row)
int ii_NumIndexAttrs
Definition: execnodes.h:146
#define InvalidOid
Definition: postgres_ext.h:36
bool ii_Unique
Definition: execnodes.h:158
List * ii_Expressions
Definition: execnodes.h:148
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:147
#define InvalidAttrNumber
Definition: attnum.h:23
Oid * ii_ExclusionOps
Definition: execnodes.h:152
int i
#define elog
Definition: elog.h:219
Oid ii_Am
Definition: execnodes.h:163

◆ EstimateReindexStateSpace()

Size EstimateReindexStateSpace ( void  )

Definition at line 4067 of file index.c.

References list_length(), mul_size(), and offsetof.

Referenced by InitializeParallelDSM().

4068 {
4071 }
static List * pendingReindexedIndexes
Definition: index.c:3954
unsigned int Oid
Definition: postgres_ext.h:31
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
static int list_length(const List *l)
Definition: pg_list.h:89
#define offsetof(type, field)
Definition: c.h:611

◆ FormIndexDatum()

void FormIndexDatum ( IndexInfo indexInfo,
TupleTableSlot slot,
EState estate,
Datum values,
bool isnull 
)

Definition at line 1981 of file index.c.

References Assert, elog, ERROR, ExecEvalExprSwitchContext(), ExecPrepareExprList(), GetPerTupleExprContext, i, IndexInfo::ii_Expressions, IndexInfo::ii_ExpressionsState, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, lfirst, list_head(), lnext, NIL, and slot_getattr().

Referenced by CatalogIndexInsert(), check_exclusion_or_unique_constraint(), comparetup_cluster(), compute_index_stats(), ExecCheckIndexConstraints(), ExecInsertIndexTuples(), get_actual_variable_range(), IndexBuildHeapRangeScan(), IndexCheckExclusion(), unique_key_recheck(), and validate_index_heapscan().

1986 {
1987  ListCell *indexpr_item;
1988  int i;
1989 
1990  if (indexInfo->ii_Expressions != NIL &&
1991  indexInfo->ii_ExpressionsState == NIL)
1992  {
1993  /* First time through, set up expression evaluation state */
1994  indexInfo->ii_ExpressionsState =
1995  ExecPrepareExprList(indexInfo->ii_Expressions, estate);
1996  /* Check caller has set up context correctly */
1997  Assert(GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
1998  }
1999  indexpr_item = list_head(indexInfo->ii_ExpressionsState);
2000 
2001  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
2002  {
2003  int keycol = indexInfo->ii_KeyAttrNumbers[i];
2004  Datum iDatum;
2005  bool isNull;
2006 
2007  if (keycol != 0)
2008  {
2009  /*
2010  * Plain index column; get the value we need directly from the
2011  * heap tuple.
2012  */
2013  iDatum = slot_getattr(slot, keycol, &isNull);
2014  }
2015  else
2016  {
2017  /*
2018  * Index expression --- need to evaluate it.
2019  */
2020  if (indexpr_item == NULL)
2021  elog(ERROR, "wrong number of index expressions");
2022  iDatum = ExecEvalExprSwitchContext((ExprState *) lfirst(indexpr_item),
2023  GetPerTupleExprContext(estate),
2024  &isNull);
2025  indexpr_item = lnext(indexpr_item);
2026  }
2027  values[i] = iDatum;
2028  isnull[i] = isNull;
2029  }
2030 
2031  if (indexpr_item != NULL)
2032  elog(ERROR, "wrong number of index expressions");
2033 }
#define NIL
Definition: pg_list.h:69
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:297
#define GetPerTupleExprContext(estate)
Definition: executor.h:490
List * ii_ExpressionsState
Definition: execnodes.h:149
#define ERROR
Definition: elog.h:43
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition: execExpr.c:561
uintptr_t Datum
Definition: postgres.h:365
int ii_NumIndexAttrs
Definition: execnodes.h:146
List * ii_Expressions
Definition: execnodes.h:148
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:147
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int i
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1142
#define elog
Definition: elog.h:219

◆ index_build()

void index_build ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
bool  isprimary,
bool  isreindex,
bool  parallel 
)

Definition at line 2220 of file index.c.

References IndexAmRoutine::ambuild, IndexAmRoutine::ambuildempty, Assert, AtEOXact_GUC(), BTREE_AM_OID, CatalogTupleUpdate(), CommandCounterIncrement(), DEBUG1, EarlyPruningEnabled, elog, ereport, errmsg(), errmsg_plural(), ERROR, GETSTRUCT, GetUserIdAndSecContext(), heap_close, heap_freetuple(), heap_open(), IndexBuildResult::heap_tuples, HeapTupleIsValid, IndexInfo::ii_BrokenHotChain, IndexInfo::ii_Concurrent, IndexInfo::ii_ExclusionOps, IndexInfo::ii_ParallelWorkers, IndexBuildResult::index_tuples, index_update_stats(), IndexCheckExclusion(), IndexRelationId, INDEXRELID, INIT_FORKNUM, IsNormalProcessingMode, NewGUCNestLevel(), ObjectIdGetDatum, plan_create_index_workers(), PointerIsValid, RelationData::rd_amroutine, RelationData::rd_rel, RelationData::rd_smgr, RelationGetRelationName, RelationGetRelid, RelationIsValid, RelationOpenSmgr, RELPERSISTENCE_UNLOGGED, RowExclusiveLock, SearchSysCacheCopy1, SECURITY_RESTRICTED_OPERATION, SetUserIdAndSecContext(), smgrcreate(), smgrexists(), and HeapTupleData::t_self.

Referenced by build_indices(), DefineIndex(), index_create(), reindex_index(), and RelationTruncateIndexes().

2226 {
2227  IndexBuildResult *stats;
2228  Oid save_userid;
2229  int save_sec_context;
2230  int save_nestlevel;
2231 
2232  /*
2233  * sanity checks
2234  */
2235  Assert(RelationIsValid(indexRelation));
2236  Assert(PointerIsValid(indexRelation->rd_amroutine));
2237  Assert(PointerIsValid(indexRelation->rd_amroutine->ambuild));
2238  Assert(PointerIsValid(indexRelation->rd_amroutine->ambuildempty));
2239 
2240  /*
2241  * Determine worker process details for parallel CREATE INDEX. Currently,
2242  * only btree has support for parallel builds.
2243  *
2244  * Note that planner considers parallel safety for us.
2245  */
2246  if (parallel && IsNormalProcessingMode() &&
2247  indexRelation->rd_rel->relam == BTREE_AM_OID)
2248  indexInfo->ii_ParallelWorkers =
2250  RelationGetRelid(indexRelation));
2251 
2252  if (indexInfo->ii_ParallelWorkers == 0)
2253  ereport(DEBUG1,
2254  (errmsg("building index \"%s\" on table \"%s\" serially",
2255  RelationGetRelationName(indexRelation),
2256  RelationGetRelationName(heapRelation))));
2257  else
2258  ereport(DEBUG1,
2259  (errmsg_plural("building index \"%s\" on table \"%s\" with request for %d parallel worker",
2260  "building index \"%s\" on table \"%s\" with request for %d parallel workers",
2261  indexInfo->ii_ParallelWorkers,
2262  RelationGetRelationName(indexRelation),
2263  RelationGetRelationName(heapRelation),
2264  indexInfo->ii_ParallelWorkers)));
2265 
2266  /*
2267  * Switch to the table owner's userid, so that any index functions are run
2268  * as that user. Also lock down security-restricted operations and
2269  * arrange to make GUC variable changes local to this command.
2270  */
2271  GetUserIdAndSecContext(&save_userid, &save_sec_context);
2272  SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
2273  save_sec_context | SECURITY_RESTRICTED_OPERATION);
2274  save_nestlevel = NewGUCNestLevel();
2275 
2276  /*
2277  * Call the access method's build procedure
2278  */
2279  stats = indexRelation->rd_amroutine->ambuild(heapRelation, indexRelation,
2280  indexInfo);
2281  Assert(PointerIsValid(stats));
2282 
2283  /*
2284  * If this is an unlogged index, we may need to write out an init fork for
2285  * it -- but we must first check whether one already exists. If, for
2286  * example, an unlogged relation is truncated in the transaction that
2287  * created it, or truncated twice in a subsequent transaction, the
2288  * relfilenode won't change, and nothing needs to be done here.
2289  */
2290  if (indexRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
2291  !smgrexists(indexRelation->rd_smgr, INIT_FORKNUM))
2292  {
2293  RelationOpenSmgr(indexRelation);
2294  smgrcreate(indexRelation->rd_smgr, INIT_FORKNUM, false);
2295  indexRelation->rd_amroutine->ambuildempty(indexRelation);
2296  }
2297 
2298  /*
2299  * If we found any potentially broken HOT chains, mark the index as not
2300  * being usable until the current transaction is below the event horizon.
2301  * See src/backend/access/heap/README.HOT for discussion. Also set this
2302  * if early pruning/vacuuming is enabled for the heap relation. While it
2303  * might become safe to use the index earlier based on actual cleanup
2304  * activity and other active transactions, the test for that would be much
2305  * more complex and would require some form of blocking, so keep it simple
2306  * and fast by just using the current transaction.
2307  *
2308  * However, when reindexing an existing index, we should do nothing here.
2309  * Any HOT chains that are broken with respect to the index must predate
2310  * the index's original creation, so there is no need to change the
2311  * index's usability horizon. Moreover, we *must not* try to change the
2312  * index's pg_index entry while reindexing pg_index itself, and this
2313  * optimization nicely prevents that. The more complex rules needed for a
2314  * reindex are handled separately after this function returns.
2315  *
2316  * We also need not set indcheckxmin during a concurrent index build,
2317  * because we won't set indisvalid true until all transactions that care
2318  * about the broken HOT chains or early pruning/vacuuming are gone.
2319  *
2320  * Therefore, this code path can only be taken during non-concurrent
2321  * CREATE INDEX. Thus the fact that heap_update will set the pg_index
2322  * tuple's xmin doesn't matter, because that tuple was created in the
2323  * current transaction anyway. That also means we don't need to worry
2324  * about any concurrent readers of the tuple; no other transaction can see
2325  * it yet.
2326  */
2327  if ((indexInfo->ii_BrokenHotChain || EarlyPruningEnabled(heapRelation)) &&
2328  !isreindex &&
2329  !indexInfo->ii_Concurrent)
2330  {
2331  Oid indexId = RelationGetRelid(indexRelation);
2332  Relation pg_index;
2333  HeapTuple indexTuple;
2334  Form_pg_index indexForm;
2335 
2337 
2338  indexTuple = SearchSysCacheCopy1(INDEXRELID,
2339  ObjectIdGetDatum(indexId));
2340  if (!HeapTupleIsValid(indexTuple))
2341  elog(ERROR, "cache lookup failed for index %u", indexId);
2342  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
2343 
2344  /* If it's a new index, indcheckxmin shouldn't be set ... */
2345  Assert(!indexForm->indcheckxmin);
2346 
2347  indexForm->indcheckxmin = true;
2348  CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
2349 
2350  heap_freetuple(indexTuple);
2351  heap_close(pg_index, RowExclusiveLock);
2352  }
2353 
2354  /*
2355  * Update heap and index pg_class rows
2356  */
2357  index_update_stats(heapRelation,
2358  true,
2359  isprimary,
2360  stats->heap_tuples);
2361 
2362  index_update_stats(indexRelation,
2363  false,
2364  false,
2365  stats->index_tuples);
2366 
2367  /* Make the updated catalog row versions visible */
2369 
2370  /*
2371  * If it's for an exclusion constraint, make a second pass over the heap
2372  * to verify that the constraint is satisfied. We must not do this until
2373  * the index is fully valid. (Broken HOT chains shouldn't matter, though;
2374  * see comments for IndexCheckExclusion.)
2375  */
2376  if (indexInfo->ii_ExclusionOps != NULL)
2377  IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
2378 
2379  /* Roll back any GUC changes executed by index functions */
2380  AtEOXact_GUC(false, save_nestlevel);
2381 
2382  /* Restore userid and security context */
2383  SetUserIdAndSecContext(save_userid, save_sec_context);
2384 }
#define DEBUG1
Definition: elog.h:25
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:376
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:172
#define SECURITY_RESTRICTED_OPERATION
Definition: miscadmin.h:295
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:396
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:850
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define IndexRelationId
Definition: pg_index.h:29
#define BTREE_AM_OID
Definition: pg_am.h:70
#define heap_close(r, l)
Definition: heapam.h:97
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:287
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:181
#define RelationOpenSmgr(relation)
Definition: rel.h:469
#define EarlyPruningEnabled(rel)
Definition: snapmgr.h:46
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ambuild_function ambuild
Definition: amapi.h:198
#define RelationIsValid(relation)
Definition: rel.h:398
ItemPointerData t_self
Definition: htup.h:65
#define IsNormalProcessingMode()
Definition: miscadmin.h:370
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:389
#define RowExclusiveLock
Definition: lockdefs.h:38
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:5127
#define RelationGetRelationName(relation)
Definition: rel.h:445
bool ii_BrokenHotChain
Definition: execnodes.h:161
static void IndexCheckExclusion(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo)
Definition: index.c:2915
#define ereport(elevel, rest)
Definition: elog.h:122
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
void CommandCounterIncrement(void)
Definition: xact.c:915
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
int ii_ParallelWorkers
Definition: execnodes.h:162
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
int plan_create_index_workers(Oid tableOid, Oid indexOid)
Definition: planner.c:5813
bool ii_Concurrent
Definition: execnodes.h:160
static void index_update_stats(Relation rel, bool hasindex, bool isprimary, double reltuples)
Definition: index.c:2059
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int NewGUCNestLevel(void)
Definition: guc.c:5113
Oid * ii_ExclusionOps
Definition: execnodes.h:152
int errmsg(const char *fmt,...)
Definition: elog.c:797
ambuildempty_function ambuildempty
Definition: amapi.h:199
#define elog
Definition: elog.h:219
#define PointerIsValid(pointer)
Definition: c.h:582
#define RelationGetRelid(relation)
Definition: rel.h:425
double index_tuples
Definition: genam.h:33
double heap_tuples
Definition: genam.h:32

◆ index_check_primary_key()

void index_check_primary_key ( Relation  heapRel,
IndexInfo indexInfo,
bool  is_alter_table 
)

Definition at line 213 of file index.c.

References AlterTableInternal(), AT_SetNotNull, ATTNUM, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, i, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, Int16GetDatum, lappend(), makeNode, AlterTableCmd::name, NameStr, NIL, ObjectIdGetDatum, pstrdup(), RelationGetRelationName, RelationGetRelid, relationHasPrimaryKey(), ReleaseSysCache(), SearchSysCache2(), and AlterTableCmd::subtype.

Referenced by ATExecAddIndexConstraint(), and DefineIndex().

216 {
217  List *cmds;
218  int i;
219 
220  /*
221  * If ALTER TABLE, check that there isn't already a PRIMARY KEY. In CREATE
222  * TABLE, we have faith that the parser rejected multiple pkey clauses;
223  * and CREATE INDEX doesn't have a way to say PRIMARY KEY, so it's no
224  * problem either.
225  */
226  if (is_alter_table &&
227  relationHasPrimaryKey(heapRel))
228  {
229  ereport(ERROR,
230  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
231  errmsg("multiple primary keys for table \"%s\" are not allowed",
232  RelationGetRelationName(heapRel))));
233  }
234 
235  /*
236  * Check that all of the attributes in a primary key are marked as not
237  * null, otherwise attempt to ALTER TABLE .. SET NOT NULL
238  */
239  cmds = NIL;
240  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
241  {
242  AttrNumber attnum = indexInfo->ii_KeyAttrNumbers[i];
243  HeapTuple atttuple;
244  Form_pg_attribute attform;
245 
246  if (attnum == 0)
247  ereport(ERROR,
248  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
249  errmsg("primary keys cannot be expressions")));
250 
251  /* System attributes are never null, so no need to check */
252  if (attnum < 0)
253  continue;
254 
255  atttuple = SearchSysCache2(ATTNUM,
257  Int16GetDatum(attnum));
258  if (!HeapTupleIsValid(atttuple))
259  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
260  attnum, RelationGetRelid(heapRel));
261  attform = (Form_pg_attribute) GETSTRUCT(atttuple);
262 
263  if (!attform->attnotnull)
264  {
265  /* Add a subcommand to make this one NOT NULL */
267 
268  cmd->subtype = AT_SetNotNull;
269  cmd->name = pstrdup(NameStr(attform->attname));
270  cmds = lappend(cmds, cmd);
271  }
272 
273  ReleaseSysCache(atttuple);
274  }
275 
276  /*
277  * XXX: possible future improvement: when being called from ALTER TABLE,
278  * it would be more efficient to merge this with the outer ALTER TABLE, so
279  * as to avoid two scans. But that seems to complicate DefineIndex's API
280  * unduly.
281  */
282  if (cmds)
283  AlterTableInternal(RelationGetRelid(heapRel), cmds, true);
284 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
char * pstrdup(const char *in)
Definition: mcxt.c:1063
#define Int16GetDatum(X)
Definition: postgres.h:434
int errcode(int sqlerrcode)
Definition: elog.c:575
AlterTableType subtype
Definition: parsenodes.h:1803
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
int ii_NumIndexAttrs
Definition: execnodes.h:146
static bool relationHasPrimaryKey(Relation rel)
Definition: index.c:160
#define makeNode(_type_)
Definition: nodes.h:561
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:147
void AlterTableInternal(Oid relid, List *cmds, bool recurse)
Definition: tablecmds.c:3219
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:425

◆ index_constraint_create()

ObjectAddress index_constraint_create ( Relation  heapRelation,
Oid  indexRelationId,
Oid  parentConstraintId,
IndexInfo indexInfo,
const char *  constraintName,
char  constraintType,
bits16  constr_flags,
bool  allow_system_table_mods,
bool  is_internal 
)

Definition at line 1210 of file index.c.

References CreateTrigStmt::args, Assert, CatalogTupleUpdate(), ObjectAddress::classId, CreateTrigStmt::columns, CONSTRAINT_EXCLUSION, CONSTRAINT_PRIMARY, ConstraintRelationId, CreateTrigStmt::constrrel, CreateConstraintEntry(), CreateTrigger(), CreateTrigStmt::deferrable, deleteDependencyRecordsForClass(), DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, DEPENDENCY_INTERNAL_AUTO, elog, ereport, errcode(), errmsg(), ERROR, CreateTrigStmt::events, CreateTrigStmt::funcname, GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Expressions, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, INDEX_CONSTR_CREATE_DEFERRABLE, INDEX_CONSTR_CREATE_INIT_DEFERRED, INDEX_CONSTR_CREATE_MARK_AS_PRIMARY, INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS, INDEX_CONSTR_CREATE_UPDATE_INDEX, index_update_stats(), IndexRelationId, INDEXRELID, CreateTrigStmt::initdeferred, InvalidOid, InvokeObjectPostAlterHookArg, IsBootstrapProcessingMode, CreateTrigStmt::isconstraint, IsNormalProcessingMode, IsSystemRelation(), makeNode, NIL, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, recordDependencyOn(), CreateTrigStmt::relation, RelationGetNamespace, RelationGetRelid, RelationRelationId, CreateTrigStmt::row, RowExclusiveLock, SearchSysCacheCopy1, SystemFuncName(), HeapTupleData::t_self, CreateTrigStmt::timing, TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT, TRIGGER_TYPE_UPDATE, CreateTrigStmt::trigname, and CreateTrigStmt::whenClause.

Referenced by ATExecAddIndexConstraint(), and index_create().

1219 {
1220  Oid namespaceId = RelationGetNamespace(heapRelation);
1221  ObjectAddress myself,
1222  referenced;
1223  Oid conOid;
1224  bool deferrable;
1225  bool initdeferred;
1226  bool mark_as_primary;
1227  bool islocal;
1228  bool noinherit;
1229  int inhcount;
1230 
1231  deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
1232  initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;
1233  mark_as_primary = (constr_flags & INDEX_CONSTR_CREATE_MARK_AS_PRIMARY) != 0;
1234 
1235  /* constraint creation support doesn't work while bootstrapping */
1237 
1238  /* enforce system-table restriction */
1239  if (!allow_system_table_mods &&
1240  IsSystemRelation(heapRelation) &&
1242  ereport(ERROR,
1243  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1244  errmsg("user-defined indexes on system catalog tables are not supported")));
1245 
1246  /* primary/unique constraints shouldn't have any expressions */
1247  if (indexInfo->ii_Expressions &&
1248  constraintType != CONSTRAINT_EXCLUSION)
1249  elog(ERROR, "constraints cannot have index expressions");
1250 
1251  /*
1252  * If we're manufacturing a constraint for a pre-existing index, we need
1253  * to get rid of the existing auto dependencies for the index (the ones
1254  * that index_create() would have made instead of calling this function).
1255  *
1256  * Note: this code would not necessarily do the right thing if the index
1257  * has any expressions or predicate, but we'd never be turning such an
1258  * index into a UNIQUE or PRIMARY KEY constraint.
1259  */
1260  if (constr_flags & INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS)
1263 
1264  if (OidIsValid(parentConstraintId))
1265  {
1266  islocal = false;
1267  inhcount = 1;
1268  noinherit = false;
1269  }
1270  else
1271  {
1272  islocal = true;
1273  inhcount = 0;
1274  noinherit = true;
1275  }
1276 
1277  /*
1278  * Construct a pg_constraint entry.
1279  */
1280  conOid = CreateConstraintEntry(constraintName,
1281  namespaceId,
1282  constraintType,
1283  deferrable,
1284  initdeferred,
1285  true,
1286  RelationGetRelid(heapRelation),
1287  indexInfo->ii_KeyAttrNumbers,
1288  indexInfo->ii_NumIndexAttrs,
1289  InvalidOid, /* no domain */
1290  indexRelationId, /* index OID */
1291  InvalidOid, /* no foreign key */
1292  NULL,
1293  NULL,
1294  NULL,
1295  NULL,
1296  0,
1297  ' ',
1298  ' ',
1299  ' ',
1300  indexInfo->ii_ExclusionOps,
1301  NULL, /* no check constraint */
1302  NULL,
1303  NULL,
1304  islocal,
1305  inhcount,
1306  noinherit,
1307  is_internal);
1308 
1309  /*
1310  * Register the index as internally dependent on the constraint.
1311  *
1312  * Note that the constraint has a dependency on the table, so we don't
1313  * need (or want) any direct dependency from the index to the table.
1314  */
1315  myself.classId = RelationRelationId;
1316  myself.objectId = indexRelationId;
1317  myself.objectSubId = 0;
1318 
1319  referenced.classId = ConstraintRelationId;
1320  referenced.objectId = conOid;
1321  referenced.objectSubId = 0;
1322 
1323  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1324 
1325  /*
1326  * Also, if this is a constraint on a partition, mark it as depending
1327  * on the constraint in the parent.
1328  */
1329  if (OidIsValid(parentConstraintId))
1330  {
1331  ObjectAddress parentConstr;
1332 
1333  ObjectAddressSet(parentConstr, ConstraintRelationId, parentConstraintId);
1334  recordDependencyOn(&referenced, &parentConstr, DEPENDENCY_INTERNAL_AUTO);
1335  }
1336 
1337  /*
1338  * If the constraint is deferrable, create the deferred uniqueness
1339  * checking trigger. (The trigger will be given an internal dependency on
1340  * the constraint by CreateTrigger.)
1341  */
1342  if (deferrable)
1343  {
1344  CreateTrigStmt *trigger;
1345 
1346  trigger = makeNode(CreateTrigStmt);
1347  trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ?
1348  "PK_ConstraintTrigger" :
1349  "Unique_ConstraintTrigger";
1350  trigger->relation = NULL;
1351  trigger->funcname = SystemFuncName("unique_key_recheck");
1352  trigger->args = NIL;
1353  trigger->row = true;
1354  trigger->timing = TRIGGER_TYPE_AFTER;
1356  trigger->columns = NIL;
1357  trigger->whenClause = NULL;
1358  trigger->isconstraint = true;
1359  trigger->deferrable = true;
1360  trigger->initdeferred = initdeferred;
1361  trigger->constrrel = NULL;
1362 
1363  (void) CreateTrigger(trigger, NULL, RelationGetRelid(heapRelation),
1364  InvalidOid, conOid, indexRelationId, true);
1365  }
1366 
1367  /*
1368  * If needed, mark the table as having a primary key. We assume it can't
1369  * have been so marked already, so no need to clear the flag in the other
1370  * case.
1371  *
1372  * Note: this might better be done by callers. We do it here to avoid
1373  * exposing index_update_stats() globally, but that wouldn't be necessary
1374  * if relhaspkey went away.
1375  */
1376  if (mark_as_primary)
1377  index_update_stats(heapRelation,
1378  true,
1379  true,
1380  -1.0);
1381 
1382  /*
1383  * If needed, mark the index as primary and/or deferred in pg_index.
1384  *
1385  * Note: When making an existing index into a constraint, caller must have
1386  * a table lock that prevents concurrent table updates; otherwise, there
1387  * is a risk that concurrent readers of the table will miss seeing this
1388  * index at all.
1389  */
1390  if ((constr_flags & INDEX_CONSTR_CREATE_UPDATE_INDEX) &&
1391  (mark_as_primary || deferrable))
1392  {
1393  Relation pg_index;
1394  HeapTuple indexTuple;
1395  Form_pg_index indexForm;
1396  bool dirty = false;
1397 
1399 
1400  indexTuple = SearchSysCacheCopy1(INDEXRELID,
1401  ObjectIdGetDatum(indexRelationId));
1402  if (!HeapTupleIsValid(indexTuple))
1403  elog(ERROR, "cache lookup failed for index %u", indexRelationId);
1404  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
1405 
1406  if (mark_as_primary && !indexForm->indisprimary)
1407  {
1408  indexForm->indisprimary = true;
1409  dirty = true;
1410  }
1411 
1412  if (deferrable && indexForm->indimmediate)
1413  {
1414  indexForm->indimmediate = false;
1415  dirty = true;
1416  }
1417 
1418  if (dirty)
1419  {
1420  CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
1421 
1422  InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
1423  InvalidOid, is_internal);
1424  }
1425 
1426  heap_freetuple(indexTuple);
1427  heap_close(pg_index, RowExclusiveLock);
1428  }
1429 
1430  return referenced;
1431 }
#define NIL
Definition: pg_list.h:69
List * SystemFuncName(char *name)
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
bool IsSystemRelation(Relation relation)
Definition: catalog.c:63
Node * whenClause
Definition: parsenodes.h:2372
#define IndexRelationId
Definition: pg_index.h:29
#define RelationRelationId
Definition: pg_class.h:29
ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, bool isInternal)
Definition: trigger.c:141
#define CONSTRAINT_EXCLUSION
int errcode(int sqlerrcode)
Definition: elog.c:575
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
#define heap_close(r, l)
Definition: heapam.h:97
#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS
Definition: index.h:77
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
#define InvokeObjectPostAlterHookArg(classId, objectId, subId, auxiliaryId, is_internal)
Definition: objectaccess.h:166
#define INDEX_CONSTR_CREATE_INIT_DEFERRED
Definition: index.h:75
#define CONSTRAINT_PRIMARY
RangeVar * constrrel
Definition: parsenodes.h:2379
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define TRIGGER_TYPE_AFTER
Definition: pg_trigger.h:112
ItemPointerData t_self
Definition: htup.h:65
#define IsNormalProcessingMode()
Definition: miscadmin.h:370
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
int ii_NumIndexAttrs
Definition: execnodes.h:146
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:241
#define TRIGGER_TYPE_UPDATE
Definition: pg_trigger.h:102
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:561
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
List * ii_Expressions
Definition: execnodes.h:148
#define Assert(condition)
Definition: c.h:688
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define TRIGGER_TYPE_INSERT
Definition: pg_trigger.h:100
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:147
#define INDEX_CONSTR_CREATE_UPDATE_INDEX
Definition: index.h:76
static void index_update_stats(Relation rel, bool hasindex, bool isprimary, double reltuples)
Definition: index.c:2059
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
Oid * ii_ExclusionOps
Definition: execnodes.h:152
int errmsg(const char *fmt,...)
Definition: elog.c:797
RangeVar * relation
Definition: parsenodes.h:2363
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define RelationGetRelid(relation)
Definition: rel.h:425
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid relId, const int16 *constraintKey, int constraintNKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, const char *conSrc, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
Definition: pg_constraint.c:49
#define INDEX_CONSTR_CREATE_DEFERRABLE
Definition: index.h:74
#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY
Definition: index.h:73
#define RelationGetNamespace(relation)
Definition: rel.h:452

◆ index_create()

Oid index_create ( Relation  heapRelation,
const char *  indexRelationName,
Oid  indexRelationId,
Oid  parentIndexRelid,
Oid  parentConstraintId,
Oid  relFileNode,
IndexInfo indexInfo,
List indexColNames,
Oid  accessMethodObjectId,
Oid  tableSpaceId,
Oid collationObjectId,
Oid classObjectId,
int16 coloptions,
Datum  reloptions,
bits16  flags,
bits16  constr_flags,
bool  allow_system_table_mods,
bool  is_internal,
Oid constraintId 
)

Definition at line 732 of file index.c.

References AccessExclusiveLock, AppendAttributeTuples(), Assert, binary_upgrade_next_index_pg_class_oid, ObjectAddress::classId, CollationRelationId, CommandCounterIncrement(), CONSTRAINT_EXCLUSION, CONSTRAINT_PRIMARY, CONSTRAINT_UNIQUE, ConstructTupleDescriptor(), DEFAULT_COLLATION_OID, DEPENDENCY_AUTO, DEPENDENCY_INTERNAL_AUTO, DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), errmsg_internal(), ERROR, get_relname_relid(), GetNewRelFileNode(), GLOBALTABLESPACE_OID, heap_close, heap_create(), heap_open(), i, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Expressions, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_Predicate, IndexInfo::ii_Unique, index_build(), index_close(), INDEX_CONSTR_CREATE_DEFERRABLE, index_constraint_create(), INDEX_CREATE_ADD_CONSTRAINT, INDEX_CREATE_CONCURRENT, INDEX_CREATE_IF_NOT_EXISTS, INDEX_CREATE_INVALID, INDEX_CREATE_IS_PRIMARY, INDEX_CREATE_PARTITIONED, INDEX_CREATE_SKIP_BUILD, index_register(), index_update_stats(), InitializeAttributeOids(), InsertPgClassTuple(), InvalidOid, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, IsSystemRelation(), LockRelation(), NoLock, NOTICE, ObjectAddress::objectId, ObjectAddress::objectSubId, OidIsValid, OperatorClassRelationId, RelationData::rd_indexcxt, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetNamespace, RelationGetRelid, RelationInitIndexAccessInfo(), RelationIsMapped, RelationRelationId, RELKIND_INDEX, RELKIND_PARTITIONED_INDEX, RowExclusiveLock, StoreSingleInheritance(), and UpdateIndexRelation().

Referenced by create_toast_table(), and DefineIndex().

751 {
752  Oid heapRelationId = RelationGetRelid(heapRelation);
753  Relation pg_class;
754  Relation indexRelation;
755  TupleDesc indexTupDesc;
756  bool shared_relation;
757  bool mapped_relation;
758  bool is_exclusion;
759  Oid namespaceId;
760  int i;
761  char relpersistence;
762  bool isprimary = (flags & INDEX_CREATE_IS_PRIMARY) != 0;
763  bool invalid = (flags & INDEX_CREATE_INVALID) != 0;
764  bool concurrent = (flags & INDEX_CREATE_CONCURRENT) != 0;
765  bool partitioned = (flags & INDEX_CREATE_PARTITIONED) != 0;
766  char relkind;
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 */
772  Assert(!partitioned || (flags & INDEX_CREATE_SKIP_BUILD));
773 
774  relkind = partitioned ? RELKIND_PARTITIONED_INDEX : RELKIND_INDEX;
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 relfilenode 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 
796  if (!allow_system_table_mods &&
797  IsSystemRelation(heapRelation) &&
799  ereport(ERROR,
800  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
801  errmsg("user-defined indexes on system catalog tables are not supported")));
802 
803  /*
804  * concurrent index build on a system catalog is unsafe because we tend to
805  * release locks before committing in catalogs
806  */
807  if (concurrent &&
808  IsSystemRelation(heapRelation))
809  ereport(ERROR,
810  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
811  errmsg("concurrent index creation on system catalog tables is not supported")));
812 
813  /*
814  * This case is currently not supported, but there's no way to ask for it
815  * in the grammar anyway, so it can't happen.
816  */
817  if (concurrent && is_exclusion)
818  ereport(ERROR,
819  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
820  errmsg_internal("concurrent index creation for exclusion constraints is not supported")));
821 
822  /*
823  * We cannot allow indexing a shared relation after initdb (because
824  * there's no way to make the entry in other databases' pg_class).
825  */
826  if (shared_relation && !IsBootstrapProcessingMode())
827  ereport(ERROR,
828  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
829  errmsg("shared indexes cannot be created after initdb")));
830 
831  /*
832  * Shared relations must be in pg_global, too (last-ditch check)
833  */
834  if (shared_relation && tableSpaceId != GLOBALTABLESPACE_OID)
835  elog(ERROR, "shared relations must be placed in pg_global tablespace");
836 
837  if (get_relname_relid(indexRelationName, namespaceId))
838  {
839  if ((flags & INDEX_CREATE_IF_NOT_EXISTS) != 0)
840  {
841  ereport(NOTICE,
842  (errcode(ERRCODE_DUPLICATE_TABLE),
843  errmsg("relation \"%s\" already exists, skipping",
844  indexRelationName)));
845  heap_close(pg_class, RowExclusiveLock);
846  return InvalidOid;
847  }
848 
849  ereport(ERROR,
850  (errcode(ERRCODE_DUPLICATE_TABLE),
851  errmsg("relation \"%s\" already exists",
852  indexRelationName)));
853  }
854 
855  /*
856  * construct tuple descriptor for index tuples
857  */
858  indexTupDesc = ConstructTupleDescriptor(heapRelation,
859  indexInfo,
860  indexColNames,
861  accessMethodObjectId,
862  collationObjectId,
863  classObjectId);
864 
865  /*
866  * Allocate an OID for the index, unless we were told what to use.
867  *
868  * The OID will be the relfilenode as well, so make sure it doesn't
869  * collide with either pg_class OIDs or existing physical files.
870  */
871  if (!OidIsValid(indexRelationId))
872  {
873  /* Use binary-upgrade override for pg_class.oid/relfilenode? */
874  if (IsBinaryUpgrade)
875  {
877  ereport(ERROR,
878  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
879  errmsg("pg_class index OID value not set when in binary upgrade mode")));
880 
881  indexRelationId = binary_upgrade_next_index_pg_class_oid;
883  }
884  else
885  {
886  indexRelationId =
887  GetNewRelFileNode(tableSpaceId, pg_class, relpersistence);
888  }
889  }
890 
891  /*
892  * create the index relation's relcache entry and, if necessary, the
893  * physical disk file. (If we fail further down, it's the smgr's
894  * responsibility to remove the disk file again, if any.)
895  */
896  indexRelation = heap_create(indexRelationName,
897  namespaceId,
898  tableSpaceId,
899  indexRelationId,
900  relFileNode,
901  indexTupDesc,
902  relkind,
903  relpersistence,
904  shared_relation,
905  mapped_relation,
906  allow_system_table_mods);
907 
908  Assert(indexRelationId == RelationGetRelid(indexRelation));
909 
910  /*
911  * Obtain exclusive lock on it. Although no other transactions can see it
912  * until we commit, this prevents deadlock-risk complaints from lock
913  * manager in cases such as CLUSTER.
914  */
915  LockRelation(indexRelation, AccessExclusiveLock);
916 
917  /*
918  * Fill in fields of the index's pg_class entry that are not set correctly
919  * by heap_create.
920  *
921  * XXX should have a cleaner way to create cataloged indexes
922  */
923  indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
924  indexRelation->rd_rel->relam = accessMethodObjectId;
925  indexRelation->rd_rel->relhasoids = false;
926 
927  /*
928  * store index's pg_class entry
929  */
930  InsertPgClassTuple(pg_class, indexRelation,
931  RelationGetRelid(indexRelation),
932  (Datum) 0,
933  reloptions);
934 
935  /* done with pg_class */
936  heap_close(pg_class, RowExclusiveLock);
937 
938  /*
939  * now update the object id's of all the attribute tuple forms in the
940  * index relation's tuple descriptor
941  */
942  InitializeAttributeOids(indexRelation,
943  indexInfo->ii_NumIndexAttrs,
944  indexRelationId);
945 
946  /*
947  * append ATTRIBUTE tuples for the index
948  */
949  AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs);
950 
951  /* ----------------
952  * update pg_index
953  * (append INDEX tuple)
954  *
955  * Note that this stows away a representation of "predicate".
956  * (Or, could define a rule to maintain the predicate) --Nels, Feb '92
957  * ----------------
958  */
959  UpdateIndexRelation(indexRelationId, heapRelationId, parentIndexRelid,
960  indexInfo,
961  collationObjectId, classObjectId, coloptions,
962  isprimary, is_exclusion,
963  (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) == 0,
964  !concurrent && !invalid,
965  !concurrent);
966 
967  /* update pg_inherits, if needed */
968  if (OidIsValid(parentIndexRelid))
969  StoreSingleInheritance(indexRelationId, parentIndexRelid, 1);
970 
971  /*
972  * Register constraint and dependencies for the index.
973  *
974  * If the index is from a CONSTRAINT clause, construct a pg_constraint
975  * entry. The index will be linked to the constraint, which in turn is
976  * linked to the table. If it's not a CONSTRAINT, we need to make a
977  * dependency directly on the table.
978  *
979  * We don't need a dependency on the namespace, because there'll be an
980  * indirect dependency via our parent table.
981  *
982  * During bootstrap we can't register any dependencies, and we don't try
983  * to make a constraint either.
984  */
986  {
987  ObjectAddress myself,
988  referenced;
989 
990  myself.classId = RelationRelationId;
991  myself.objectId = indexRelationId;
992  myself.objectSubId = 0;
993 
994  if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0)
995  {
996  char constraintType;
997  ObjectAddress localaddr;
998 
999  if (isprimary)
1000  constraintType = CONSTRAINT_PRIMARY;
1001  else if (indexInfo->ii_Unique)
1002  constraintType = CONSTRAINT_UNIQUE;
1003  else if (is_exclusion)
1004  constraintType = CONSTRAINT_EXCLUSION;
1005  else
1006  {
1007  elog(ERROR, "constraint must be PRIMARY, UNIQUE or EXCLUDE");
1008  constraintType = 0; /* keep compiler quiet */
1009  }
1010 
1011  localaddr = index_constraint_create(heapRelation,
1012  indexRelationId,
1013  parentConstraintId,
1014  indexInfo,
1015  indexRelationName,
1016  constraintType,
1017  constr_flags,
1018  allow_system_table_mods,
1019  is_internal);
1020  if (constraintId)
1021  *constraintId = localaddr.objectId;
1022  }
1023  else
1024  {
1025  bool have_simple_col = false;
1026  DependencyType deptype;
1027 
1028  deptype = OidIsValid(parentIndexRelid) ? DEPENDENCY_INTERNAL_AUTO : DEPENDENCY_AUTO;
1029 
1030  /* Create auto dependencies on simply-referenced columns */
1031  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1032  {
1033  if (indexInfo->ii_KeyAttrNumbers[i] != 0)
1034  {
1035  referenced.classId = RelationRelationId;
1036  referenced.objectId = heapRelationId;
1037  referenced.objectSubId = indexInfo->ii_KeyAttrNumbers[i];
1038 
1039  recordDependencyOn(&myself, &referenced, deptype);
1040 
1041  have_simple_col = true;
1042  }
1043  }
1044 
1045  /*
1046  * If there are no simply-referenced columns, give the index an
1047  * auto dependency on the whole table. In most cases, this will
1048  * be redundant, but it might not be if the index expressions and
1049  * predicate contain no Vars or only whole-row Vars.
1050  */
1051  if (!have_simple_col)
1052  {
1053  referenced.classId = RelationRelationId;
1054  referenced.objectId = heapRelationId;
1055  referenced.objectSubId = 0;
1056 
1057  recordDependencyOn(&myself, &referenced, deptype);
1058  }
1059  }
1060 
1061  /* Store dependency on parent index, if any */
1062  if (OidIsValid(parentIndexRelid))
1063  {
1064  referenced.classId = RelationRelationId;
1065  referenced.objectId = parentIndexRelid;
1066  referenced.objectSubId = 0;
1067 
1068  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL_AUTO);
1069  }
1070 
1071  /* Store dependency on collations */
1072  /* The default collation is pinned, so don't bother recording it */
1073  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1074  {
1075  if (OidIsValid(collationObjectId[i]) &&
1076  collationObjectId[i] != DEFAULT_COLLATION_OID)
1077  {
1078  referenced.classId = CollationRelationId;
1079  referenced.objectId = collationObjectId[i];
1080  referenced.objectSubId = 0;
1081 
1082  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1083  }
1084  }
1085 
1086  /* Store dependency on operator classes */
1087  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1088  {
1089  referenced.classId = OperatorClassRelationId;
1090  referenced.objectId = classObjectId[i];
1091  referenced.objectSubId = 0;
1092 
1093  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1094  }
1095 
1096  /* Store dependencies on anything mentioned in index expressions */
1097  if (indexInfo->ii_Expressions)
1098  {
1100  (Node *) indexInfo->ii_Expressions,
1101  heapRelationId,
1103  DEPENDENCY_AUTO, false);
1104  }
1105 
1106  /* Store dependencies on anything mentioned in predicate */
1107  if (indexInfo->ii_Predicate)
1108  {
1110  (Node *) indexInfo->ii_Predicate,
1111  heapRelationId,
1113  DEPENDENCY_AUTO, false);
1114  }
1115  }
1116  else
1117  {
1118  /* Bootstrap mode - assert we weren't asked for constraint support */
1119  Assert((flags & INDEX_CREATE_ADD_CONSTRAINT) == 0);
1120  }
1121 
1122  /* Post creation hook for new index */
1124  indexRelationId, 0, is_internal);
1125 
1126  /*
1127  * Advance the command counter so that we can see the newly-entered
1128  * catalog tuples for the index.
1129  */
1131 
1132  /*
1133  * In bootstrap mode, we have to fill in the index strategy structure with
1134  * information from the catalogs. If we aren't bootstrapping, then the
1135  * relcache entry has already been rebuilt thanks to sinval update during
1136  * CommandCounterIncrement.
1137  */
1139  RelationInitIndexAccessInfo(indexRelation);
1140  else
1141  Assert(indexRelation->rd_indexcxt != NULL);
1142 
1143  /*
1144  * If this is bootstrap (initdb) time, then we don't actually fill in the
1145  * index yet. We'll be creating more indexes and classes later, so we
1146  * delay filling them in until just before we're done with bootstrapping.
1147  * Similarly, if the caller specified to skip the build then filling the
1148  * index is delayed till later (ALTER TABLE can save work in some cases
1149  * with this). Otherwise, we call the AM routine that constructs the
1150  * index.
1151  */
1153  {
1154  index_register(heapRelationId, indexRelationId, indexInfo);
1155  }
1156  else if ((flags & INDEX_CREATE_SKIP_BUILD) != 0)
1157  {
1158  /*
1159  * Caller is responsible for filling the index later on. However,
1160  * we'd better make sure that the heap relation is correctly marked as
1161  * having an index.
1162  */
1163  index_update_stats(heapRelation,
1164  true,
1165  isprimary,
1166  -1.0);
1167  /* Make the above update visible */
1169  }
1170  else
1171  {
1172  index_build(heapRelation, indexRelation, indexInfo, isprimary, false,
1173  true);
1174  }
1175 
1176  /*
1177  * Close the index; but we keep the lock that we acquired above until end
1178  * of transaction. Closing the heap is caller's responsibility.
1179  */
1180  index_close(indexRelation, NoLock);
1181 
1182  return indexRelationId;
1183 }
DependencyType
Definition: dependency.h:87
static void UpdateIndexRelation(Oid indexoid, Oid heapoid, Oid parentIndexId, IndexInfo *indexInfo, Oid *collationOids, Oid *classOids, int16 *coloptions, bool primary, bool isexclusion, bool immediate, bool isvalid, bool isready)
Definition: index.c:570
List * ii_Predicate
Definition: execnodes.h:150
bool IsSystemRelation(Relation relation)
Definition: catalog.c:63
#define INDEX_CREATE_IF_NOT_EXISTS
Definition: index.h:49
#define INDEX_CREATE_INVALID
Definition: index.h:51
#define RelationRelationId
Definition: pg_class.h:29
static void InitializeAttributeOids(Relation indexRelation, int numatts, Oid indexoid)
Definition: index.c:507
Oid binary_upgrade_next_index_pg_class_oid
Definition: index.c:81
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
Definition: nodes.h:513
#define CONSTRAINT_EXCLUSION
int errcode(int sqlerrcode)
Definition: elog.c:575
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isprimary, bool isreindex, bool parallel)
Definition: index.c:2220
#define CONSTRAINT_UNIQUE
#define OidIsValid(objectId)
Definition: c.h:594
bool IsBinaryUpgrade
Definition: globals.c:102
#define CONSTRAINT_PRIMARY
void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
Definition: heap.c:767
#define ERROR
Definition: elog.h:43
Relation heap_create(const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid relfilenode, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods)
Definition: heap.c:250
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1687
#define NoLock
Definition: lockdefs.h:34
#define IsNormalProcessingMode()
Definition: miscadmin.h:370
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
#define RowExclusiveLock
Definition: lockdefs.h:38
static TupleDesc ConstructTupleDescriptor(Relation heapRelation, IndexInfo *indexInfo, List *indexColNames, Oid accessMethodObjectId, Oid *collationObjectId, Oid *classObjectId)
Definition: index.c:292
void StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber)
Definition: pg_inherits.c:413
void index_register(Oid heap, Oid ind, IndexInfo *indexInfo)
Definition: bootstrap.c:1079
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_PARTITIONED_INDEX
Definition: pg_class.h:169
static void AppendAttributeTuples(Relation indexRelation, int numatts)
Definition: index.c:525
#define RelationIsMapped(relation)
Definition: rel.h:462
uintptr_t Datum
Definition: postgres.h:365
void CommandCounterIncrement(void)
Definition: xact.c:915
int ii_NumIndexAttrs
Definition: execnodes.h:146
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:147
#define CollationRelationId
Definition: pg_collation.h:30
#define INDEX_CREATE_IS_PRIMARY
Definition: index.h:45
#define InvalidOid
Definition: postgres_ext.h:36
#define INDEX_CREATE_CONCURRENT
Definition: index.h:48
#define NOTICE
Definition: elog.h:37
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
bool ii_Unique
Definition: execnodes.h:158
List * ii_Expressions
Definition: execnodes.h:148
#define Assert(condition)
Definition: c.h:688
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:395
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:147
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool ignore_self)
Definition: dependency.c:1404
static void index_update_stats(Relation rel, bool hasindex, bool isprimary, double reltuples)
Definition: index.c:2059
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
void RelationInitIndexAccessInfo(Relation relation)
Definition: relcache.c:1480
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
#define INDEX_CREATE_SKIP_BUILD
Definition: index.h:47
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define INDEX_CREATE_PARTITIONED
Definition: index.h:50
Oid * ii_ExclusionOps
Definition: execnodes.h:152
int errmsg(const char *fmt,...)
Definition: elog.c:797
MemoryContext rd_indexcxt
Definition: rel.h:179
int i
void LockRelation(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:199
#define RELKIND_INDEX
Definition: pg_class.h:161
#define elog
Definition: elog.h:219
#define INDEX_CREATE_ADD_CONSTRAINT
Definition: index.h:46
#define RelationGetRelid(relation)
Definition: rel.h:425
#define INDEX_CONSTR_CREATE_DEFERRABLE
Definition: index.h:74
ObjectAddress index_constraint_create(Relation heapRelation, Oid indexRelationId, Oid parentConstraintId, IndexInfo *indexInfo, const char *constraintName, char constraintType, bits16 constr_flags, bool allow_system_table_mods, bool is_internal)
Definition: index.c:1210
#define RelationGetNamespace(relation)
Definition: rel.h:452

◆ index_drop()

void index_drop ( Oid  indexId,
bool  concurrent 
)

Definition at line 1440 of file index.c.

References AccessExclusiveLock, Anum_pg_index_indexprs, CacheInvalidateRelcache(), CatalogTupleDelete(), CheckTableNotInUse(), CommitTransactionCommand(), LockRelId::dbId, DeleteAttributeTuples(), DeleteInheritsTuple(), DeleteRelationTuple(), elog, ereport, errcode(), errmsg(), ERROR, GetTopTransactionIdIfAny(), heap_attisnull(), heap_close, heap_open(), HeapTupleIsValid, index_close(), INDEX_DROP_CLEAR_VALID, INDEX_DROP_SET_DEAD, index_open(), index_set_state_flags(), IndexGetRelation(), IndexRelationId, INDEXRELID, InvalidOid, InvalidTransactionId, LockRelationIdForSession(), LockInfoData::lockRelId, NoLock, ObjectIdGetDatum, PopActiveSnapshot(), RelationData::rd_lockInfo, RelationData::rd_rel, RelationDropStorage(), RelationForgetRelation(), ReleaseSysCache(), LockRelId::relId, RELKIND_PARTITIONED_INDEX, RemoveStatistics(), RowExclusiveLock, SearchSysCache1(), SET_LOCKTAG_RELATION, ShareUpdateExclusiveLock, StartTransactionCommand(), HeapTupleData::t_self, TransferPredicateLocksToHeapRelation(), UnlockRelationIdForSession(), and WaitForLockers().

Referenced by doDeletion().

1441 {
1442  Oid heapId;
1443  Relation userHeapRelation;
1444  Relation userIndexRelation;
1445  Relation indexRelation;
1446  HeapTuple tuple;
1447  bool hasexprs;
1448  LockRelId heaprelid,
1449  indexrelid;
1450  LOCKTAG heaplocktag;
1451  LOCKMODE lockmode;
1452 
1453  /*
1454  * To drop an index safely, we must grab exclusive lock on its parent
1455  * table. Exclusive lock on the index alone is insufficient because
1456  * another backend might be about to execute a query on the parent table.
1457  * If it relies on a previously cached list of index OIDs, then it could
1458  * attempt to access the just-dropped index. We must therefore take a
1459  * table lock strong enough to prevent all queries on the table from
1460  * proceeding until we commit and send out a shared-cache-inval notice
1461  * that will make them update their index lists.
1462  *
1463  * In the concurrent case we avoid this requirement by disabling index use
1464  * in multiple steps and waiting out any transactions that might be using
1465  * the index, so we don't need exclusive lock on the parent table. Instead
1466  * we take ShareUpdateExclusiveLock, to ensure that two sessions aren't
1467  * doing CREATE/DROP INDEX CONCURRENTLY on the same index. (We will get
1468  * AccessExclusiveLock on the index below, once we're sure nobody else is
1469  * using it.)
1470  */
1471  heapId = IndexGetRelation(indexId, false);
1472  lockmode = concurrent ? ShareUpdateExclusiveLock : AccessExclusiveLock;
1473  userHeapRelation = heap_open(heapId, lockmode);
1474  userIndexRelation = index_open(indexId, lockmode);
1475 
1476  /*
1477  * We might still have open queries using it in our own session, which the
1478  * above locking won't prevent, so test explicitly.
1479  */
1480  CheckTableNotInUse(userIndexRelation, "DROP INDEX");
1481 
1482  /*
1483  * Drop Index Concurrently is more or less the reverse process of Create
1484  * Index Concurrently.
1485  *
1486  * First we unset indisvalid so queries starting afterwards don't use the
1487  * index to answer queries anymore. We have to keep indisready = true so
1488  * transactions that are still scanning the index can continue to see
1489  * valid index contents. For instance, if they are using READ COMMITTED
1490  * mode, and another transaction makes changes and commits, they need to
1491  * see those new tuples in the index.
1492  *
1493  * After all transactions that could possibly have used the index for
1494  * queries end, we can unset indisready and indislive, then wait till
1495  * nobody could be touching it anymore. (Note: we need indislive because
1496  * this state must be distinct from the initial state during CREATE INDEX
1497  * CONCURRENTLY, which has indislive true while indisready and indisvalid
1498  * are false. That's because in that state, transactions must examine the
1499  * index for HOT-safety decisions, while in this state we don't want them
1500  * to open it at all.)
1501  *
1502  * Since all predicate locks on the index are about to be made invalid, we
1503  * must promote them to predicate locks on the heap. In the
1504  * non-concurrent case we can just do that now. In the concurrent case
1505  * it's a bit trickier. The predicate locks must be moved when there are
1506  * no index scans in progress on the index and no more can subsequently
1507  * start, so that no new predicate locks can be made on the index. Also,
1508  * they must be moved before heap inserts stop maintaining the index, else
1509  * the conflict with the predicate lock on the index gap could be missed
1510  * before the lock on the heap relation is in place to detect a conflict
1511  * based on the heap tuple insert.
1512  */
1513  if (concurrent)
1514  {
1515  /*
1516  * We must commit our transaction in order to make the first pg_index
1517  * state update visible to other sessions. If the DROP machinery has
1518  * already performed any other actions (removal of other objects,
1519  * pg_depend entries, etc), the commit would make those actions
1520  * permanent, which would leave us with inconsistent catalog state if
1521  * we fail partway through the following sequence. Since DROP INDEX
1522  * CONCURRENTLY is restricted to dropping just one index that has no
1523  * dependencies, we should get here before anything's been done ---
1524  * but let's check that to be sure. We can verify that the current
1525  * transaction has not executed any transactional updates by checking
1526  * that no XID has been assigned.
1527  */
1529  ereport(ERROR,
1530  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1531  errmsg("DROP INDEX CONCURRENTLY must be first action in transaction")));
1532 
1533  /*
1534  * Mark index invalid by updating its pg_index entry
1535  */
1537 
1538  /*
1539  * Invalidate the relcache for the table, so that after this commit
1540  * all sessions will refresh any cached plans that might reference the
1541  * index.
1542  */
1543  CacheInvalidateRelcache(userHeapRelation);
1544 
1545  /* save lockrelid and locktag for below, then close but keep locks */
1546  heaprelid = userHeapRelation->rd_lockInfo.lockRelId;
1547  SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
1548  indexrelid = userIndexRelation->rd_lockInfo.lockRelId;
1549 
1550  heap_close(userHeapRelation, NoLock);
1551  index_close(userIndexRelation, NoLock);
1552 
1553  /*
1554  * We must commit our current transaction so that the indisvalid
1555  * update becomes visible to other transactions; then start another.
1556  * Note that any previously-built data structures are lost in the
1557  * commit. The only data we keep past here are the relation IDs.
1558  *
1559  * Before committing, get a session-level lock on the table, to ensure
1560  * that neither it nor the index can be dropped before we finish. This
1561  * cannot block, even if someone else is waiting for access, because
1562  * we already have the same lock within our transaction.
1563  */
1566 
1570 
1571  /*
1572  * Now we must wait until no running transaction could be using the
1573  * index for a query. Use AccessExclusiveLock here to check for
1574  * running transactions that hold locks of any kind on the table. Note
1575  * we do not need to worry about xacts that open the table for reading
1576  * after this point; they will see the index as invalid when they open
1577  * the relation.
1578  *
1579  * Note: the reason we use actual lock acquisition here, rather than
1580  * just checking the ProcArray and sleeping, is that deadlock is
1581  * possible if one of the transactions in question is blocked trying
1582  * to acquire an exclusive lock on our table. The lock code will
1583  * detect deadlock and error out properly.
1584  */
1585  WaitForLockers(heaplocktag, AccessExclusiveLock);
1586 
1587  /*
1588  * No more predicate locks will be acquired on this index, and we're
1589  * about to stop doing inserts into the index which could show
1590  * conflicts with existing predicate locks, so now is the time to move
1591  * them to the heap relation.
1592  */
1593  userHeapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
1594  userIndexRelation = index_open(indexId, ShareUpdateExclusiveLock);
1595  TransferPredicateLocksToHeapRelation(userIndexRelation);
1596 
1597  /*
1598  * Now we are sure that nobody uses the index for queries; they just
1599  * might have it open for updating it. So now we can unset indisready
1600  * and indislive, then wait till nobody could be using it at all
1601  * anymore.
1602  */
1604 
1605  /*
1606  * Invalidate the relcache for the table, so that after this commit
1607  * all sessions will refresh the table's index list. Forgetting just
1608  * the index's relcache entry is not enough.
1609  */
1610  CacheInvalidateRelcache(userHeapRelation);
1611 
1612  /*
1613  * Close the relations again, though still holding session lock.
1614  */
1615  heap_close(userHeapRelation, NoLock);
1616  index_close(userIndexRelation, NoLock);
1617 
1618  /*
1619  * Again, commit the transaction to make the pg_index update visible
1620  * to other sessions.
1621  */
1624 
1625  /*
1626  * Wait till every transaction that saw the old index state has
1627  * finished.
1628  */
1629  WaitForLockers(heaplocktag, AccessExclusiveLock);
1630 
1631  /*
1632  * Re-open relations to allow us to complete our actions.
1633  *
1634  * At this point, nothing should be accessing the index, but lets
1635  * leave nothing to chance and grab AccessExclusiveLock on the index
1636  * before the physical deletion.
1637  */
1638  userHeapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
1639  userIndexRelation = index_open(indexId, AccessExclusiveLock);
1640  }
1641  else
1642  {
1643  /* Not concurrent, so just transfer predicate locks and we're good */
1644  TransferPredicateLocksToHeapRelation(userIndexRelation);
1645  }
1646 
1647  /*
1648  * Schedule physical removal of the files (if any)
1649  */
1650  if (userIndexRelation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
1651  RelationDropStorage(userIndexRelation);
1652 
1653  /*
1654  * Close and flush the index's relcache entry, to ensure relcache doesn't
1655  * try to rebuild it while we're deleting catalog entries. We keep the
1656  * lock though.
1657  */
1658  index_close(userIndexRelation, NoLock);
1659 
1660  RelationForgetRelation(indexId);
1661 
1662  /*
1663  * fix INDEX relation, and check for expressional index
1664  */
1665  indexRelation = heap_open(IndexRelationId, RowExclusiveLock);
1666 
1667  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
1668  if (!HeapTupleIsValid(tuple))
1669  elog(ERROR, "cache lookup failed for index %u", indexId);
1670 
1671  hasexprs = !heap_attisnull(tuple, Anum_pg_index_indexprs);
1672 
1673  CatalogTupleDelete(indexRelation, &tuple->t_self);
1674 
1675  ReleaseSysCache(tuple);
1676  heap_close(indexRelation, RowExclusiveLock);
1677 
1678  /*
1679  * if it has any expression columns, we might have stored statistics about
1680  * them.
1681  */
1682  if (hasexprs)
1683  RemoveStatistics(indexId, 0);
1684 
1685  /*
1686  * fix ATTRIBUTE relation
1687  */
1688  DeleteAttributeTuples(indexId);
1689 
1690  /*
1691  * fix RELATION relation
1692  */
1693  DeleteRelationTuple(indexId);
1694 
1695  /*
1696  * fix INHERITS relation
1697  */
1698  DeleteInheritsTuple(indexId, InvalidOid);
1699 
1700  /*
1701  * We are presently too lazy to attempt to compute the new correct value
1702  * of relhasindex (the next VACUUM will fix it if necessary). So there is
1703  * no need to update the pg_class tuple for the owning relation. But we
1704  * must send out a shared-cache-inval notice on the owning relation to
1705  * ensure other backends update their relcache lists of indexes. (In the
1706  * concurrent case, this is redundant but harmless.)
1707  */
1708  CacheInvalidateRelcache(userHeapRelation);
1709 
1710  /*
1711  * Close owning rel, but keep lock
1712  */
1713  heap_close(userHeapRelation, NoLock);
1714 
1715  /*
1716  * Release the session locks before we go.
1717  */
1718  if (concurrent)
1719  {
1722  }
1723 }
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3551
LockRelId lockRelId
Definition: rel.h:44
int LOCKMODE
Definition: lockdefs.h:26
void index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
Definition: index.c:3472
#define IndexRelationId
Definition: pg_index.h:29
void CommitTransactionCommand(void)
Definition: xact.c:2745
Oid dbId
Definition: rel.h:39
Definition: lock.h:178
bool DeleteInheritsTuple(Oid inhrelid, Oid inhparent)
Definition: pg_inherits.c:450
int errcode(int sqlerrcode)
Definition: elog.c:575
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2660
void PopActiveSnapshot(void)
Definition: snapmgr.c:812
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:312
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Definition: rel.h:36
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:299
ItemPointerData t_self
Definition: htup.h:65
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:193
#define NoLock
Definition: lockdefs.h:34
LockInfoData rd_lockInfo
Definition: rel.h:117
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:296
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:405
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3115
#define ereport(elevel, rest)
Definition: elog.h:122
void TransferPredicateLocksToHeapRelation(Relation relation)
Definition: predicate.c:3090
#define RELKIND_PARTITIONED_INDEX
Definition: pg_class.h:169
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void RelationDropStorage(Relation rel)
Definition: storage.c:145
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode)
Definition: lmgr.c:837
#define InvalidOid
Definition: postgres_ext.h:36
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1437
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void StartTransactionCommand(void)
Definition: xact.c:2674
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1466
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:2774
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
#define Anum_pg_index_indexprs
Definition: pg_index.h:91
Oid relId
Definition: rel.h:38

◆ index_set_state_flags()

void index_set_state_flags ( Oid  indexId,
IndexStateFlagsAction  action 
)

Definition at line 3472 of file index.c.

References Assert, elog, ERROR, GETSTRUCT, GetTopTransactionIdIfAny(), heap_close, heap_inplace_update(), heap_open(), HeapTupleIsValid, INDEX_CREATE_SET_READY, INDEX_CREATE_SET_VALID, INDEX_DROP_CLEAR_VALID, INDEX_DROP_SET_DEAD, IndexRelationId, INDEXRELID, InvalidTransactionId, ObjectIdGetDatum, RowExclusiveLock, and SearchSysCacheCopy1.

Referenced by DefineIndex(), and index_drop().

3473 {
3474  Relation pg_index;
3475  HeapTuple indexTuple;
3476  Form_pg_index indexForm;
3477 
3478  /* Assert that current xact hasn't done any transactional updates */
3480 
3481  /* Open pg_index and fetch a writable copy of the index's tuple */
3483 
3484  indexTuple = SearchSysCacheCopy1(INDEXRELID,
3485  ObjectIdGetDatum(indexId));
3486  if (!HeapTupleIsValid(indexTuple))
3487  elog(ERROR, "cache lookup failed for index %u", indexId);
3488  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
3489 
3490  /* Perform the requested state change on the copy */
3491  switch (action)
3492  {
3494  /* Set indisready during a CREATE INDEX CONCURRENTLY sequence */
3495  Assert(indexForm->indislive);
3496  Assert(!indexForm->indisready);
3497  Assert(!indexForm->indisvalid);
3498  indexForm->indisready = true;
3499  break;
3501  /* Set indisvalid during a CREATE INDEX CONCURRENTLY sequence */
3502  Assert(indexForm->indislive);
3503  Assert(indexForm->indisready);
3504  Assert(!indexForm->indisvalid);
3505  indexForm->indisvalid = true;
3506  break;
3508 
3509  /*
3510  * Clear indisvalid during a DROP INDEX CONCURRENTLY sequence
3511  *
3512  * If indisready == true we leave it set so the index still gets
3513  * maintained by active transactions. We only need to ensure that
3514  * indisvalid is false. (We don't assert that either is initially
3515  * true, though, since we want to be able to retry a DROP INDEX
3516  * CONCURRENTLY that failed partway through.)
3517  *
3518  * Note: the CLUSTER logic assumes that indisclustered cannot be
3519  * set on any invalid index, so clear that flag too.
3520  */
3521  indexForm->indisvalid = false;
3522  indexForm->indisclustered = false;
3523  break;
3524  case INDEX_DROP_SET_DEAD:
3525 
3526  /*
3527  * Clear indisready/indislive during DROP INDEX CONCURRENTLY
3528  *
3529  * We clear both indisready and indislive, because we not only
3530  * want to stop updates, we want to prevent sessions from touching
3531  * the index at all.
3532  */
3533  Assert(!indexForm->indisvalid);
3534  indexForm->indisready = false;
3535  indexForm->indislive = false;
3536  break;
3537  }
3538 
3539  /* ... and write it back in-place */
3540  heap_inplace_update(pg_index, indexTuple);
3541 
3542  heap_close(pg_index, RowExclusiveLock);
3543 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define IndexRelationId
Definition: pg_index.h:29
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:405
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
void heap_inplace_update(Relation relation, HeapTuple tuple)
Definition: heapam.c:6271
#define elog
Definition: elog.h:219

◆ IndexBuildHeapRangeScan()

double IndexBuildHeapRangeScan ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
bool  allow_sync,
bool  anyvisible,
BlockNumber  start_blockno,
BlockNumber  end_blockno,
IndexBuildCallback  callback,
void *  callback_state,
HeapScanDesc  scan 
)

Definition at line 2437 of file index.c.

References Assert, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, callback(), CHECK_FOR_INTERRUPTS, CreateExecutorState(), ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, elog, ERROR, ExecDropSingleTupleTableSlot(), ExecPrepareQual(), ExecQual(), ExecStoreTuple(), FormIndexDatum(), ForwardScanDirection, FreeExecutorState(), GetOldestXmin(), GetPerTupleExprContext, GetTransactionSnapshot(), heap_beginscan_strat(), heap_endscan(), heap_get_root_tuples(), heap_getnext(), heap_setscanlimits(), HEAPTUPLE_DEAD, HEAPTUPLE_DELETE_IN_PROGRESS, HEAPTUPLE_INSERT_IN_PROGRESS, HEAPTUPLE_LIVE, HEAPTUPLE_RECENTLY_DEAD, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleIsHeapOnly, HeapTupleIsHotUpdated, HeapTupleSatisfiesVacuum(), IndexInfo::ii_BrokenHotChain, IndexInfo::ii_Concurrent, IndexInfo::ii_ExclusionOps, IndexInfo::ii_ExpressionsState, IndexInfo::ii_Predicate, IndexInfo::ii_PredicateState, IndexInfo::ii_Unique, INDEX_MAX_KEYS, InvalidBlockNumber, InvalidBuffer, InvalidTransactionId, IsBootstrapProcessingMode, IsMVCCSnapshot, IsSystemRelation(), ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, ItemPointerSetOffsetNumber, LockBuffer(), MakeSingleTupleTableSlot(), MaxHeapTuplesPerPage, MemoryContextReset(), NIL, OffsetNumberIsValid, OidIsValid, OldestXmin, PROCARRAY_FLAGS_VACUUM, RelationData::rd_rel, RegisterSnapshot(), RelationGetDescr, RelationGetRelationName, HeapScanDescData::rs_cblock, HeapScanDescData::rs_cbuf, HeapScanDescData::rs_snapshot, SnapshotAny, HeapTupleData::t_data, HeapTupleData::t_self, TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, UnregisterSnapshot(), values, WARNING, XactLockTableWait(), and XLTW_InsertIndexUnique.

Referenced by IndexBuildHeapScan(), and summarize_range().

2447 {
2448  bool is_system_catalog;
2449  bool checking_uniqueness;
2450  HeapTuple heapTuple;
2452  bool isnull[INDEX_MAX_KEYS];
2453  double reltuples;
2454  ExprState *predicate;
2455  TupleTableSlot *slot;
2456  EState *estate;
2457  ExprContext *econtext;
2458  Snapshot snapshot;
2459  bool need_unregister_snapshot = false;
2461  BlockNumber root_blkno = InvalidBlockNumber;
2462  OffsetNumber root_offsets[MaxHeapTuplesPerPage];
2463 
2464  /*
2465  * sanity checks
2466  */
2467  Assert(OidIsValid(indexRelation->rd_rel->relam));
2468 
2469  /* Remember if it's a system catalog */
2470  is_system_catalog = IsSystemRelation(heapRelation);
2471 
2472  /* See whether we're verifying uniqueness/exclusion properties */
2473  checking_uniqueness = (indexInfo->ii_Unique ||
2474  indexInfo->ii_ExclusionOps != NULL);
2475 
2476  /*
2477  * "Any visible" mode is not compatible with uniqueness checks; make sure
2478  * only one of those is requested.
2479  */
2480  Assert(!(anyvisible && checking_uniqueness));
2481 
2482  /*
2483  * Need an EState for evaluation of index expressions and partial-index
2484  * predicates. Also a slot to hold the current tuple.
2485  */
2486  estate = CreateExecutorState();
2487  econtext = GetPerTupleExprContext(estate);
2488  slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
2489 
2490  /* Arrange for econtext's scan tuple to be the tuple under test */
2491  econtext->ecxt_scantuple = slot;
2492 
2493  /* Set up execution state for predicate, if any. */
2494  predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
2495 
2496  /*
2497  * Prepare for scan of the base relation. In a normal index build, we use
2498  * SnapshotAny because we must retrieve all tuples and do our own time
2499  * qual checks (because we have to index RECENTLY_DEAD tuples). In a
2500  * concurrent build, or during bootstrap, we take a regular MVCC snapshot
2501  * and index whatever's live according to that.
2502  */
2503  OldestXmin = InvalidTransactionId;
2504 
2505  /* okay to ignore lazy VACUUMs here */
2506  if (!IsBootstrapProcessingMode() && !indexInfo->ii_Concurrent)
2507  OldestXmin = GetOldestXmin(heapRelation, PROCARRAY_FLAGS_VACUUM);
2508 
2509  if (!scan)
2510  {
2511  /*
2512  * Serial index build.
2513  *
2514  * Must begin our own heap scan in this case. We may also need to
2515  * register a snapshot whose lifetime is under our direct control.
2516  */
2517  if (!TransactionIdIsValid(OldestXmin))
2518  {
2520  need_unregister_snapshot = true;
2521  }
2522  else
2523  snapshot = SnapshotAny;
2524 
2525  scan = heap_beginscan_strat(heapRelation, /* relation */
2526  snapshot, /* snapshot */
2527  0, /* number of keys */
2528  NULL, /* scan key */
2529  true, /* buffer access strategy OK */
2530  allow_sync); /* syncscan OK? */
2531  }
2532  else
2533  {
2534  /*
2535  * Parallel index build.
2536  *
2537  * Parallel case never registers/unregisters own snapshot. Snapshot
2538  * is taken from parallel heap scan, and is SnapshotAny or an MVCC
2539  * snapshot, based on same criteria as serial case.
2540  */
2542  Assert(allow_sync);
2543  snapshot = scan->rs_snapshot;
2544  }
2545 
2546  /*
2547  * Must call GetOldestXmin() with SnapshotAny. Should never call
2548  * GetOldestXmin() with MVCC snapshot. (It's especially worth checking
2549  * this for parallel builds, since ambuild routines that support parallel
2550  * builds must work these details out for themselves.)
2551  */
2552  Assert(snapshot == SnapshotAny || IsMVCCSnapshot(snapshot));
2553  Assert(snapshot == SnapshotAny ? TransactionIdIsValid(OldestXmin) :
2554  !TransactionIdIsValid(OldestXmin));
2555  Assert(snapshot == SnapshotAny || !anyvisible);
2556 
2557  /* set our scan endpoints */
2558  if (!allow_sync)
2559  heap_setscanlimits(scan, start_blockno, numblocks);
2560  else
2561  {
2562  /* syncscan can only be requested on whole relation */
2563  Assert(start_blockno == 0);
2564  Assert(numblocks == InvalidBlockNumber);
2565  }
2566 
2567  reltuples = 0;
2568 
2569  /*
2570  * Scan all tuples in the base relation.
2571  */
2572  while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2573  {
2574  bool tupleIsAlive;
2575 
2577 
2578  /*
2579  * When dealing with a HOT-chain of updated tuples, we want to index
2580  * the values of the live tuple (if any), but index it under the TID
2581  * of the chain's root tuple. This approach is necessary to preserve
2582  * the HOT-chain structure in the heap. So we need to be able to find
2583  * the root item offset for every tuple that's in a HOT-chain. When
2584  * first reaching a new page of the relation, call
2585  * heap_get_root_tuples() to build a map of root item offsets on the
2586  * page.
2587  *
2588  * It might look unsafe to use this information across buffer
2589  * lock/unlock. However, we hold ShareLock on the table so no
2590  * ordinary insert/update/delete should occur; and we hold pin on the
2591  * buffer continuously while visiting the page, so no pruning
2592  * operation can occur either.
2593  *
2594  * Also, although our opinions about tuple liveness could change while
2595  * we scan the page (due to concurrent transaction commits/aborts),
2596  * the chain root locations won't, so this info doesn't need to be
2597  * rebuilt after waiting for another transaction.
2598  *
2599  * Note the implied assumption that there is no more than one live
2600  * tuple per HOT-chain --- else we could create more than one index
2601  * entry pointing to the same root tuple.
2602  */
2603  if (scan->rs_cblock != root_blkno)
2604  {
2605  Page page = BufferGetPage(scan->rs_cbuf);
2606 
2608  heap_get_root_tuples(page, root_offsets);
2610 
2611  root_blkno = scan->rs_cblock;
2612  }
2613 
2614  if (snapshot == SnapshotAny)
2615  {
2616  /* do our own time qual check */
2617  bool indexIt;
2618  TransactionId xwait;
2619 
2620  recheck:
2621 
2622  /*
2623  * We could possibly get away with not locking the buffer here,
2624  * since caller should hold ShareLock on the relation, but let's
2625  * be conservative about it. (This remark is still correct even
2626  * with HOT-pruning: our pin on the buffer prevents pruning.)
2627  */
2629 
2630  switch (HeapTupleSatisfiesVacuum(heapTuple, OldestXmin,
2631  scan->rs_cbuf))
2632  {
2633  case HEAPTUPLE_DEAD:
2634  /* Definitely dead, we can ignore it */
2635  indexIt = false;
2636  tupleIsAlive = false;
2637  break;
2638  case HEAPTUPLE_LIVE:
2639  /* Normal case, index and unique-check it */
2640  indexIt = true;
2641  tupleIsAlive = true;
2642  break;
2644 
2645  /*
2646  * If tuple is recently deleted then we must index it
2647  * anyway to preserve MVCC semantics. (Pre-existing
2648  * transactions could try to use the index after we finish
2649  * building it, and may need to see such tuples.)
2650  *
2651  * However, if it was HOT-updated then we must only index
2652  * the live tuple at the end of the HOT-chain. Since this
2653  * breaks semantics for pre-existing snapshots, mark the
2654  * index as unusable for them.
2655  */
2656  if (HeapTupleIsHotUpdated(heapTuple))
2657  {
2658  indexIt = false;
2659  /* mark the index as unsafe for old snapshots */
2660  indexInfo->ii_BrokenHotChain = true;
2661  }
2662  else
2663  indexIt = true;
2664  /* In any case, exclude the tuple from unique-checking */
2665  tupleIsAlive = false;
2666  break;
2668 
2669  /*
2670  * In "anyvisible" mode, this tuple is visible and we
2671  * don't need any further checks.
2672  */
2673  if (anyvisible)
2674  {
2675  indexIt = true;
2676  tupleIsAlive = true;
2677  break;
2678  }
2679 
2680  /*
2681  * Since caller should hold ShareLock or better, normally
2682  * the only way to see this is if it was inserted earlier
2683  * in our own transaction. However, it can happen in
2684  * system catalogs, since we tend to release write lock
2685  * before commit there. Give a warning if neither case
2686  * applies.
2687  */
2688  xwait = HeapTupleHeaderGetXmin(heapTuple->t_data);
2690  {
2691  if (!is_system_catalog)
2692  elog(WARNING, "concurrent insert in progress within table \"%s\"",
2693  RelationGetRelationName(heapRelation));
2694 
2695  /*
2696  * If we are performing uniqueness checks, indexing
2697  * such a tuple could lead to a bogus uniqueness
2698  * failure. In that case we wait for the inserting
2699  * transaction to finish and check again.
2700  */
2701  if (checking_uniqueness)
2702  {
2703  /*
2704  * Must drop the lock on the buffer before we wait
2705  */
2707  XactLockTableWait(xwait, heapRelation,
2708  &heapTuple->t_self,
2711  goto recheck;
2712  }
2713  }
2714 
2715  /*
2716  * We must index such tuples, since if the index build
2717  * commits then they're good.
2718  */
2719  indexIt = true;
2720  tupleIsAlive = true;
2721  break;
2723 
2724  /*
2725  * As with INSERT_IN_PROGRESS case, this is unexpected
2726  * unless it's our own deletion or a system catalog; but
2727  * in anyvisible mode, this tuple is visible.
2728  */
2729  if (anyvisible)
2730  {
2731  indexIt = true;
2732  tupleIsAlive = false;
2733  break;
2734  }
2735 
2736  xwait = HeapTupleHeaderGetUpdateXid(heapTuple->t_data);
2738  {
2739  if (!is_system_catalog)
2740  elog(WARNING, "concurrent delete in progress within table \"%s\"",
2741  RelationGetRelationName(heapRelation));
2742 
2743  /*
2744  * If we are performing uniqueness checks, assuming
2745  * the tuple is dead could lead to missing a
2746  * uniqueness violation. In that case we wait for the
2747  * deleting transaction to finish and check again.
2748  *
2749  * Also, if it's a HOT-updated tuple, we should not
2750  * index it but rather the live tuple at the end of
2751  * the HOT-chain. However, the deleting transaction
2752  * could abort, possibly leaving this tuple as live
2753  * after all, in which case it has to be indexed. The
2754  * only way to know what to do is to wait for the
2755  * deleting transaction to finish and check again.
2756  */
2757  if (checking_uniqueness ||
2758  HeapTupleIsHotUpdated(heapTuple))
2759  {
2760  /*
2761  * Must drop the lock on the buffer before we wait
2762  */
2764  XactLockTableWait(xwait, heapRelation,
2765  &heapTuple->t_self,
2768  goto recheck;
2769  }
2770 
2771  /*
2772  * Otherwise index it but don't check for uniqueness,
2773  * the same as a RECENTLY_DEAD tuple.
2774  */
2775  indexIt = true;
2776  }
2777  else if (HeapTupleIsHotUpdated(heapTuple))
2778  {
2779  /*
2780  * It's a HOT-updated tuple deleted by our own xact.
2781  * We can assume the deletion will commit (else the
2782  * index contents don't matter), so treat the same as
2783  * RECENTLY_DEAD HOT-updated tuples.
2784  */
2785  indexIt = false;
2786  /* mark the index as unsafe for old snapshots */
2787  indexInfo->ii_BrokenHotChain = true;
2788  }
2789  else
2790  {
2791  /*
2792  * It's a regular tuple deleted by our own xact. Index
2793  * it but don't check for uniqueness, the same as a
2794  * RECENTLY_DEAD tuple.
2795  */
2796  indexIt = true;
2797  }
2798  /* In any case, exclude the tuple from unique-checking */
2799  tupleIsAlive = false;
2800  break;
2801  default:
2802  elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
2803  indexIt = tupleIsAlive = false; /* keep compiler quiet */
2804  break;
2805  }
2806 
2808 
2809  if (!indexIt)
2810  continue;
2811  }
2812  else
2813  {
2814  /* heap_getnext did the time qual check */
2815  tupleIsAlive = true;
2816  }
2817 
2818  reltuples += 1;
2819 
2821 
2822  /* Set up for predicate or expression evaluation */
2823  ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
2824 
2825  /*
2826  * In a partial index, discard tuples that don't satisfy the
2827  * predicate.
2828  */
2829  if (predicate != NULL)
2830  {
2831  if (!ExecQual(predicate, econtext))
2832  continue;
2833  }
2834 
2835  /*
2836  * For the current heap tuple, extract all the attributes we use in
2837  * this index, and note which are null. This also performs evaluation
2838  * of any expressions needed.
2839  */
2840  FormIndexDatum(indexInfo,
2841  slot,
2842  estate,
2843  values,
2844  isnull);
2845 
2846  /*
2847  * You'd think we should go ahead and build the index tuple here, but
2848  * some index AMs want to do further processing on the data first. So
2849  * pass the values[] and isnull[] arrays, instead.
2850  */
2851 
2852  if (HeapTupleIsHeapOnly(heapTuple))
2853  {
2854  /*
2855  * For a heap-only tuple, pretend its TID is that of the root. See
2856  * src/backend/access/heap/README.HOT for discussion.
2857  */
2858  HeapTupleData rootTuple;
2859  OffsetNumber offnum;
2860 
2861  rootTuple = *heapTuple;
2862  offnum = ItemPointerGetOffsetNumber(&heapTuple->t_self);
2863 
2864  if (!OffsetNumberIsValid(root_offsets[offnum - 1]))
2865  elog(ERROR, "failed to find parent tuple for heap-only tuple at (%u,%u) in table \"%s\"",
2866  ItemPointerGetBlockNumber(&heapTuple->t_self),
2867  offnum, RelationGetRelationName(heapRelation));
2868 
2870  root_offsets[offnum - 1]);
2871 
2872  /* Call the AM's callback routine to process the tuple */
2873  callback(indexRelation, &rootTuple, values, isnull, tupleIsAlive,
2874  callback_state);
2875  }
2876  else
2877  {
2878  /* Call the AM's callback routine to process the tuple */
2879  callback(indexRelation, heapTuple, values, isnull, tupleIsAlive,
2880  callback_state);
2881  }
2882  }
2883 
2884  heap_endscan(scan);
2885 
2886  /* we can now forget our snapshot, if set and registered by us */
2887  if (need_unregister_snapshot)
2888  UnregisterSnapshot(snapshot);
2889 
2891 
2892  FreeExecutorState(estate);
2893 
2894  /* These may have been pointing to the now-gone estate */
2895  indexInfo->ii_ExpressionsState = NIL;
2896  indexInfo->ii_PredicateState = NULL;
2897 
2898  return reltuples;
2899 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:1981
#define NIL
Definition: pg_list.h:69
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:356
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
BlockNumber rs_cblock
Definition: relscan.h:71
List * ii_Predicate
Definition: execnodes.h:150
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1568
bool IsSystemRelation(Relation relation)
Definition: catalog.c:63
uint32 TransactionId
Definition: c.h:463
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
#define RelationGetDescr(relation)
Definition: rel.h:437
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:766
ExprState * ii_PredicateState
Definition: execnodes.h:151
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:217
#define MaxHeapTuplesPerPage
Definition: htup_details.h:580
#define InvalidBuffer
Definition: buf.h:25
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
Definition: tqual.c:1164
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:134
uint32 BlockNumber
Definition: block.h:31
#define PROCARRAY_FLAGS_VACUUM
Definition: procarray.h:52
Form_pg_class rd_rel
Definition: rel.h:114
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:362
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:304
#define OidIsValid(objectId)
Definition: c.h:594
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
void FreeExecutorState(EState *estate)
Definition: execUtils.c:185
#define HeapTupleIsHotUpdated(tuple)
Definition: htup_details.h:682
#define GetPerTupleExprContext(estate)
Definition: executor.h:490
List * ii_ExpressionsState
Definition: execnodes.h:149
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:247
Snapshot rs_snapshot
Definition: relscan.h:50
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:445
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:515
static TransactionId OldestXmin
Definition: vacuumlazy.c:138
bool ii_BrokenHotChain
Definition: execnodes.h:161
void heap_setscanlimits(HeapScanDesc scan, BlockNumber startBlk, BlockNumber numBlks)
Definition: heapam.c:327
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:232
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
void heap_get_root_tuples(Page page, OffsetNumber *root_offsets)
Definition: pruneheap.c:743
EState * CreateExecutorState(void)
Definition: execUtils.c:80
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:905
#define WARNING
Definition: elog.h:40
uintptr_t Datum
Definition: postgres.h:365
#define SnapshotAny
Definition: tqual.h:28
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1831
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1315
HeapScanDesc heap_beginscan_strat(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, bool allow_strat, bool allow_sync)
Definition: heapam.c:1418
Buffer rs_cbuf
Definition: relscan.h:72
bool ii_Unique
Definition: execnodes.h:158
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
Definition: lmgr.c:554
#define HeapTupleIsHeapOnly(tuple)
Definition: htup_details.h:691
#define Assert(condition)
Definition: c.h:688
#define IsMVCCSnapshot(snapshot)
Definition: tqual.h:31
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
#define INDEX_MAX_KEYS
#define InvalidBlockNumber
Definition: block.h:33
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:211
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
bool ii_Concurrent
Definition: execnodes.h:160
#define ItemPointerSetOffsetNumber(pointer, offsetNumber)
Definition: itemptr.h:126
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
Oid * ii_ExclusionOps
Definition: execnodes.h:152
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:40
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Pointer Page
Definition: bufpage.h:74

◆ IndexBuildHeapScan()

double IndexBuildHeapScan ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
bool  allow_sync,
IndexBuildCallback  callback,
void *  callback_state,
HeapScanDesc  scan 
)

Definition at line 2411 of file index.c.

References IndexBuildHeapRangeScan(), and InvalidBlockNumber.

Referenced by _bt_parallel_scan_and_sort(), _bt_spools_heapscan(), blbuild(), brinbuild(), ginbuild(), gistbuild(), hashbuild(), and spgbuild().

2418 {
2419  return IndexBuildHeapRangeScan(heapRelation, indexRelation,
2420  indexInfo, allow_sync,
2421  false,
2422  0, InvalidBlockNumber,
2423  callback, callback_state, scan);
2424 }
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
double IndexBuildHeapRangeScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, bool anyvisible, BlockNumber start_blockno, BlockNumber numblocks, IndexBuildCallback callback, void *callback_state, HeapScanDesc scan)
Definition: index.c:2437
#define InvalidBlockNumber
Definition: block.h:33

◆ IndexGetRelation()

Oid IndexGetRelation ( Oid  indexId,
bool  missing_ok 
)

Definition at line 3551 of file index.c.

References Assert, elog, ERROR, GETSTRUCT, HeapTupleIsValid, INDEXRELID, InvalidOid, ObjectIdGetDatum, ReleaseSysCache(), and SearchSysCache1().

Referenced by ATExecDetachPartition(), ATPostAlterTypeCleanup(), brin_desummarize_range(), brin_summarize_range(), bringetbitmap(), brinvacuumcleanup(), bt_index_check_internal(), CheckIndexCompatible(), index_drop(), RangeVarCallbackForAttachIndex(), RangeVarCallbackForDropRelation(), RangeVarCallbackForReindexIndex(), refuseDupeIndexAttach(), and reindex_index().

3552 {
3553  HeapTuple tuple;
3555  Oid result;
3556 
3557  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
3558  if (!HeapTupleIsValid(tuple))
3559  {
3560  if (missing_ok)
3561  return InvalidOid;
3562  elog(ERROR, "cache lookup failed for index %u", indexId);
3563  }
3564  index = (Form_pg_index) GETSTRUCT(tuple);
3565  Assert(index->indexrelid == indexId);
3566 
3567  result = index->indrelid;
3568  ReleaseSysCache(tuple);
3569  return result;
3570 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
unsigned int Oid
Definition: postgres_ext.h:31
Definition: type.h:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
#define elog
Definition: elog.h:219

◆ IndexSetParentIndex()

void IndexSetParentIndex ( Relation  idx,
Oid  parentOid 
)

Definition at line 2384 of file indexcmds.c.

References Anum_pg_inherits_inhparent, Anum_pg_inherits_inhrelid, Anum_pg_inherits_inhseqno, Assert, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleInsert(), deleteDependencyRecordsForClass(), DEPENDENCY_AUTO, DEPENDENCY_INTERNAL_AUTO, elog, ERROR, fix_dependencies(), GETSTRUCT, heap_form_tuple(), HeapTupleIsValid, InheritsRelationId, InheritsRelidSeqnoIndexId, Int32GetDatum, InvalidOid, Natts_pg_inherits, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, RelationData::rd_index, RelationData::rd_rel, recordDependencyOn(), relation_close(), relation_open(), RelationGetDescr, RelationGetRelid, RelationRelationId, RELKIND_INDEX, RELKIND_PARTITIONED_INDEX, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and values.

Referenced by ATExecAttachPartitionIdx(), ATExecDetachPartition(), AttachPartitionEnsureIndexes(), and DefineIndex().

2385 {
2386  Relation pg_inherits;
2387  ScanKeyData key[2];
2388  SysScanDesc scan;
2389  Oid partRelid = RelationGetRelid(partitionIdx);
2390  HeapTuple tuple;
2391  bool fix_dependencies;
2392 
2393  /* Make sure this is an index */
2394  Assert(partitionIdx->rd_rel->relkind == RELKIND_INDEX ||
2395  partitionIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX);
2396 
2397  /*
2398  * Scan pg_inherits for rows linking our index to some parent.
2399  */
2401  ScanKeyInit(&key[0],
2403  BTEqualStrategyNumber, F_OIDEQ,
2404  ObjectIdGetDatum(partRelid));
2405  ScanKeyInit(&key[1],
2407  BTEqualStrategyNumber, F_INT4EQ,
2408  Int32GetDatum(1));
2409  scan = systable_beginscan(pg_inherits, InheritsRelidSeqnoIndexId, true,
2410  NULL, 2, key);
2411  tuple = systable_getnext(scan);
2412 
2413  if (!HeapTupleIsValid(tuple))
2414  {
2415  if (parentOid == InvalidOid)
2416  {
2417  /*
2418  * No pg_inherits row, and no parent wanted: nothing to do in
2419  * this case.
2420  */
2421  fix_dependencies = false;
2422  }
2423  else
2424  {
2426  bool isnull[Natts_pg_inherits];
2427 
2428  /*
2429  * No pg_inherits row exists, and we want a parent for this index,
2430  * so insert it.
2431  */
2432  values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(partRelid);
2433  values[Anum_pg_inherits_inhparent - 1] =
2434  ObjectIdGetDatum(parentOid);
2435  values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(1);
2436  memset(isnull, false, sizeof(isnull));
2437 
2438  tuple = heap_form_tuple(RelationGetDescr(pg_inherits),
2439  values, isnull);
2440  CatalogTupleInsert(pg_inherits, tuple);
2441 
2442  fix_dependencies = true;
2443  }
2444  }
2445  else
2446  {
2447  Form_pg_inherits inhForm = (Form_pg_inherits) GETSTRUCT(tuple);
2448 
2449  if (parentOid == InvalidOid)
2450  {
2451  /*
2452  * There exists a pg_inherits row, which we want to clear; do so.
2453  */
2454  CatalogTupleDelete(pg_inherits, &tuple->t_self);
2455  fix_dependencies = true;
2456  }
2457  else
2458  {
2459  /*
2460  * A pg_inherits row exists. If it's the same we want, then we're
2461  * good; if it differs, that amounts to a corrupt catalog and
2462  * should not happen.
2463  */
2464  if (inhForm->inhparent != parentOid)
2465  {
2466  /* unexpected: we should not get called in this case */
2467  elog(ERROR, "bogus pg_inherit row: inhrelid %u inhparent %u",
2468  inhForm->inhrelid, inhForm->inhparent);
2469  }
2470 
2471  /* already in the right state */
2472  fix_dependencies = false;
2473  }
2474  }
2475 
2476  /* done with pg_inherits */
2477  systable_endscan(scan);
2478  relation_close(pg_inherits, RowExclusiveLock);
2479 
2480  if (fix_dependencies)
2481  {
2482  ObjectAddress partIdx;
2483 
2484  /*
2485  * Insert/delete pg_depend rows. If setting a parent, add an
2486  * INTERNAL_AUTO dependency to the parent index; if making standalone,
2487  * remove all existing rows and put back the regular dependency on the
2488  * table.
2489  */
2490  ObjectAddressSet(partIdx, RelationRelationId, partRelid);
2491 
2492  if (OidIsValid(parentOid))
2493  {
2494  ObjectAddress parentIdx;
2495 
2496  ObjectAddressSet(parentIdx, RelationRelationId, parentOid);
2497  recordDependencyOn(&partIdx, &parentIdx, DEPENDENCY_INTERNAL_AUTO);
2498  }
2499  else
2500  {
2501  ObjectAddress partitionTbl;
2502 
2503  ObjectAddressSet(partitionTbl, RelationRelationId,
2504  partitionIdx->rd_index->indrelid);
2505 
2509 
2510  recordDependencyOn(&partIdx, &partitionTbl, DEPENDENCY_AUTO);
2511  }
2512  }
2513 }
#define Anum_pg_inherits_inhrelid
Definition: pg_inherits.h:50
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
#define Natts_pg_inherits
Definition: pg_inherits.h:49
#define RelationRelationId
Definition: pg_class.h:29
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RELKIND_PARTITIONED_INDEX
Definition: pg_class.h:169
uintptr_t Datum
Definition: postgres.h:365
static void fix_dependencies(ArchiveHandle *AH)
#define Anum_pg_inherits_inhseqno
Definition: pg_inherits.h:52
#define Anum_pg_inherits_inhparent
Definition: pg_inherits.h:51
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:241
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:167
FormData_pg_inherits * Form_pg_inherits
Definition: pg_inherits.h:43
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define InheritsRelationId
Definition: pg_inherits.h:29
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Int32GetDatum(X)
Definition: postgres.h:462
#define RELKIND_INDEX
Definition: pg_class.h:161
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define elog
Definition: elog.h:219
#define RelationGetRelid(relation)
Definition: rel.h:425
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ reindex_index()

void reindex_index ( Oid  indexId,
bool  skip_constraint_checks,
char  relpersistence,
int  options 
)

Definition at line 3576 of file index.c.

References AccessExclusiveLock, BuildIndexInfo(), CacheInvalidateRelcache(), CatalogTupleUpdate(), CheckTableNotInUse(), EarlyPruningEnabled, elog, ereport, errcode(), errdetail_internal(), errmsg(), ERROR, get_rel_name(), GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, IndexInfo::ii_BrokenHotChain, IndexInfo::ii_ExclusionOps, IndexInfo::ii_ExclusionProcs, IndexInfo::ii_ExclusionStrats, IndexInfo::ii_Unique, index_build(), index_close(), index_open(), IndexGetRelation(), IndexRelationId, INDEXRELID, INFO, InvalidMultiXactId, InvalidTransactionId, NoLock, ObjectIdGetDatum, PG_CATCH, PG_END_TRY, PG_RE_THROW, pg_rusage_init(), pg_rusage_show(), PG_TRY, RelationData::rd_rel, REINDEXOPT_VERBOSE, RELATION_IS_OTHER_TEMP, RelationGetRelationName, RelationSetNewRelfilenode(), RELKIND_PARTITIONED_INDEX, ResetReindexProcessing(), RowExclusiveLock, SearchSysCacheCopy1, SetReindexProcessing(), ShareLock, HeapTupleData::t_self, and TransferPredicateLocksToHeapRelation().

Referenced by reindex_relation(), and ReindexIndex().

3578 {
3579  Relation iRel,
3580  heapRelation;
3581  Oid heapId;
3582  IndexInfo *indexInfo;
3583  volatile bool skipped_constraint = false;
3584  PGRUsage ru0;
3585 
3586  pg_rusage_init(&ru0);
3587 
3588  /*
3589  * Open and lock the parent heap relation. ShareLock is sufficient since
3590  * we only need to be sure no schema or data changes are going on.
3591  */
3592  heapId = IndexGetRelation(indexId, false);
3593  heapRelation = heap_open(heapId, ShareLock);
3594 
3595  /*
3596  * Open the target index relation and get an exclusive lock on it, to
3597  * ensure that no one else is touching this particular index.
3598  */
3599  iRel = index_open(indexId, AccessExclusiveLock);
3600 
3601  /*
3602  * The case of reindexing partitioned tables and indexes is handled
3603  * differently by upper layers, so this case shouldn't arise.
3604  */
3605  if (iRel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
3606  elog(ERROR, "unsupported relation kind for index \"%s\"",
3607  RelationGetRelationName(iRel));
3608 
3609  /*
3610  * Don't allow reindex on temp tables of other backends ... their local
3611  * buffer manager is not going to cope.
3612  */
3613  if (RELATION_IS_OTHER_TEMP(iRel))
3614  ereport(ERROR,
3615  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3616  errmsg("cannot reindex temporary tables of other sessions")));
3617 
3618  /*
3619  * Also check for active uses of the index in the current transaction; we
3620  * don't want to reindex underneath an open indexscan.
3621  */
3622  CheckTableNotInUse(iRel, "REINDEX INDEX");
3623 
3624  /*
3625  * All predicate locks on the index are about to be made invalid. Promote
3626  * them to relation locks on the heap.
3627  */
3629 
3630  PG_TRY();
3631  {
3632  /* Suppress use of the target index while rebuilding it */
3633  SetReindexProcessing(heapId, indexId);
3634 
3635  /* Fetch info needed for index_build */
3636  indexInfo = BuildIndexInfo(iRel);
3637 
3638  /* If requested, skip checking uniqueness/exclusion constraints */
3639  if (skip_constraint_checks)
3640  {
3641  if (indexInfo->ii_Unique || indexInfo->ii_ExclusionOps != NULL)
3642  skipped_constraint = true;
3643  indexInfo->ii_Unique = false;
3644  indexInfo->ii_ExclusionOps = NULL;
3645  indexInfo->ii_ExclusionProcs = NULL;
3646  indexInfo->ii_ExclusionStrats = NULL;
3647  }
3648 
3649  /* We'll build a new physical relation for the index */
3652 
3653  /* Initialize the index and rebuild */
3654  /* Note: we do not need to re-establish pkey setting */
3655  index_build(heapRelation, iRel, indexInfo, false, true, true);
3656  }
3657  PG_CATCH();
3658  {
3659  /* Make sure flag gets cleared on error exit */
3661  PG_RE_THROW();
3662  }
3663  PG_END_TRY();
3665 
3666  /*
3667  * If the index is marked invalid/not-ready/dead (ie, it's from a failed
3668  * CREATE INDEX CONCURRENTLY, or a DROP INDEX CONCURRENTLY failed midway),
3669  * and we didn't skip a uniqueness check, we can now mark it valid. This
3670  * allows REINDEX to be used to clean up in such cases.
3671  *
3672  * We can also reset indcheckxmin, because we have now done a
3673  * non-concurrent index build, *except* in the case where index_build
3674  * found some still-broken HOT chains. If it did, and we don't have to
3675  * change any of the other flags, we just leave indcheckxmin alone (note
3676  * that index_build won't have changed it, because this is a reindex).
3677  * This is okay and desirable because not updating the tuple leaves the
3678  * index's usability horizon (recorded as the tuple's xmin value) the same
3679  * as it was.
3680  *
3681  * But, if the index was invalid/not-ready/dead and there were broken HOT
3682  * chains, we had better force indcheckxmin true, because the normal
3683  * argument that the HOT chains couldn't conflict with the index is
3684  * suspect for an invalid index. (A conflict is definitely possible if
3685  * the index was dead. It probably shouldn't happen otherwise, but let's
3686  * be conservative.) In this case advancing the usability horizon is
3687  * appropriate.
3688  *
3689  * Another reason for avoiding unnecessary updates here is that while
3690  * reindexing pg_index itself, we must not try to update tuples in it.
3691  * pg_index's indexes should always have these flags in their clean state,
3692  * so that won't happen.
3693  *
3694  * If early pruning/vacuuming is enabled for the heap relation, the
3695  * usability horizon must be advanced to the current transaction on every
3696  * build or rebuild. pg_index is OK in this regard because catalog tables
3697  * are not subject to early cleanup.
3698  */
3699  if (!skipped_constraint)
3700  {
3701  Relation pg_index;
3702  HeapTuple indexTuple;
3703  Form_pg_index indexForm;
3704  bool index_bad;
3705  bool early_pruning_enabled = EarlyPruningEnabled(heapRelation);
3706 
3708 
3709  indexTuple = SearchSysCacheCopy1(INDEXRELID,
3710  ObjectIdGetDatum(indexId));
3711  if (!HeapTupleIsValid(indexTuple))
3712  elog(ERROR, "cache lookup failed for index %u", indexId);
3713  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
3714 
3715  index_bad = (!indexForm->indisvalid ||
3716  !indexForm->indisready ||
3717  !indexForm->indislive);
3718  if (index_bad ||
3719  (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain) ||
3720  early_pruning_enabled)
3721  {
3722  if (!indexInfo->ii_BrokenHotChain && !early_pruning_enabled)
3723  indexForm->indcheckxmin = false;
3724  else if (index_bad || early_pruning_enabled)
3725  indexForm->indcheckxmin = true;
3726  indexForm->indisvalid = true;
3727  indexForm->indisready = true;
3728  indexForm->indislive = true;
3729  CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
3730 
3731  /*
3732  * Invalidate the relcache for the table, so that after we commit
3733  * all sessions will refresh the table's index list. This ensures
3734  * that if anyone misses seeing the pg_index row during this
3735  * update, they'll refresh their list before attempting any update
3736  * on the table.
3737  */
3738  CacheInvalidateRelcache(heapRelation);
3739  }
3740 
3741  heap_close(pg_index, RowExclusiveLock);
3742  }
3743 
3744  /* Log what we did */
3746  ereport(INFO,
3747  (errmsg("index \"%s\" was reindexed",
3748  get_rel_name(indexId)),
3749  errdetail_internal("%s",
3750  pg_rusage_show(&ru0))));
3751 
3752  /* Close rels, but keep locks */
3753  index_close(iRel, NoLock);
3754  heap_close(heapRelation, NoLock);
3755 }
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3551
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3399
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
static void SetReindexProcessing(Oid heapOid, Oid indexOid)
Definition: index.c:3995
#define IndexRelationId
Definition: pg_index.h:29
Oid * ii_ExclusionProcs
Definition: execnodes.h:153
int errcode(int sqlerrcode)
Definition: elog.c:575
#define INFO
Definition: elog.h:33
#define heap_close(r, l)
Definition: heapam.h:97
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:1741
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isprimary, bool isreindex, bool parallel)
Definition: index.c:2220
#define REINDEXOPT_VERBOSE
Definition: parsenodes.h:3261
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
static void ResetReindexProcessing(void)
Definition: index.c:4012
void pg_rusage_init(PGRUsage *ru0)
Definition: pg_rusage.c:27
#define EarlyPruningEnabled(rel)
Definition: snapmgr.h:46
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
const char * pg_rusage_show(const PGRUsage *ru0)
Definition: pg_rusage.c:40
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:445
bool ii_BrokenHotChain
Definition: execnodes.h:161
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3115
#define ereport(elevel, rest)
Definition: elog.h:122
void TransferPredicateLocksToHeapRelation(Relation relation)
Definition: predicate.c:3090
#define RELKIND_PARTITIONED_INDEX
Definition: pg_class.h:169
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidMultiXactId
Definition: multixact.h:23
bool ii_Unique
Definition: execnodes.h:158
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:542
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define PG_RE_THROW()
Definition: elog.h:314
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define AccessExclusiveLock
Definition: lockdefs.h:45
Oid * ii_ExclusionOps
Definition: execnodes.h:152
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ShareLock
Definition: lockdefs.h:41
#define elog
Definition: elog.h:219
uint16 * ii_ExclusionStrats
Definition: execnodes.h:154
#define PG_TRY()
Definition: elog.h:284
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
#define PG_END_TRY()
Definition: elog.h:300

◆ reindex_relation()

bool reindex_relation ( Oid  relid,
int  flags,
int  options 
)

Definition at line 3793 of file index.c.

References Assert, ClassOidIndexId, CommandCounterIncrement(), ereport, errcode(), errmsg(), heap_close, heap_open(), INDEX_ATTR_BITMAP_ALL, InvalidOid, lappend_oid(), lfirst_oid, NIL, NoLock, OidIsValid, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, RelationData::rd_rel, reindex_index(), REINDEX_REL_CHECK_CONSTRAINTS, REINDEX_REL_FORCE_INDEXES_PERMANENT, REINDEX_REL_FORCE_INDEXES_UNLOGGED, REINDEX_REL_PROCESS_TOAST, REINDEX_REL_SUPPRESS_INDEX_USE, reindex_relation(), ReindexIsProcessingIndex(), RelationGetIndexAttrBitmap(), RelationGetIndexList(), RelationGetRelationName, RelationGetRelid, RelationRelationId, RelationSetIndexList(), RELKIND_PARTITIONED_TABLE, RELPERSISTENCE_PERMANENT, RELPERSISTENCE_UNLOGGED, ResetReindexPending(), SetReindexPending(), ShareLock, and WARNING.

Referenced by ExecuteTruncate(), finish_heap_swap(), reindex_relation(), ReindexMultipleTables(), and ReindexTable().

3794 {
3795  Relation rel;
3796  Oid toast_relid;
3797  List *indexIds;
3798  bool is_pg_class;
3799  bool result;
3800 
3801  /*
3802  * Open and lock the relation. ShareLock is sufficient since we only need
3803  * to prevent schema and data changes in it. The lock level used here
3804  * should match ReindexTable().
3805  */
3806  rel = heap_open(relid, ShareLock);
3807 
3808  /*
3809  * This may be useful when implemented someday; but that day is not today.
3810  * For now, avoid erroring out when called in a multi-table context
3811  * (REINDEX SCHEMA) and happen to come across a partitioned table. The
3812  * partitions may be reindexed on their own anyway.
3813  */
3814  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3815  {
3816  ereport(WARNING,
3817  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3818  errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
3819  RelationGetRelationName(rel))));
3820  heap_close(rel, ShareLock);
3821  return false;
3822  }
3823 
3824  toast_relid = rel->rd_rel->reltoastrelid;
3825 
3826  /*
3827  * Get the list of index OIDs for this relation. (We trust to the
3828  * relcache to get this with a sequential scan if ignoring system
3829  * indexes.)
3830  */
3831  indexIds = RelationGetIndexList(rel);
3832 
3833  /*
3834  * reindex_index will attempt to update the pg_class rows for the relation
3835  * and index. If we are processing pg_class itself, we want to make sure
3836  * that the updates do not try to insert index entries into indexes we
3837  * have not processed yet. (When we are trying to recover from corrupted
3838  * indexes, that could easily cause a crash.) We can accomplish this
3839  * because CatalogTupleInsert/CatalogTupleUpdate will use the relcache's
3840  * index list to know which indexes to update. We just force the index
3841  * list to be only the stuff we've processed.
3842  *
3843  * It is okay to not insert entries into the indexes we have not processed
3844  * yet because all of this is transaction-safe. If we fail partway
3845  * through, the updated rows are dead and it doesn't matter whether they
3846  * have index entries. Also, a new pg_class index will be created with a
3847  * correct entry for its own pg_class row because we do
3848  * RelationSetNewRelfilenode() before we do index_build().
3849  *
3850  * Note that we also clear pg_class's rd_oidindex until the loop is done,
3851  * so that that index can't be accessed either. This means we cannot
3852  * safely generate new relation OIDs while in the loop; shouldn't be a
3853  * problem.
3854  */
3855  is_pg_class = (RelationGetRelid(rel) == RelationRelationId);
3856 
3857  /* Ensure rd_indexattr is valid; see comments for RelationSetIndexList */
3858  if (is_pg_class)
3860 
3861  PG_TRY();
3862  {
3863  List *doneIndexes;
3864  ListCell *indexId;
3865  char persistence;
3866 
3867  if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
3868  {
3869  /* Suppress use of all the indexes until they are rebuilt */
3870  SetReindexPending(indexIds);
3871 
3872  /*
3873  * Make the new heap contents visible --- now things might be
3874  * inconsistent!
3875  */
3877  }
3878 
3879  /*
3880  * Compute persistence of indexes: same as that of owning rel, unless
3881  * caller specified otherwise.
3882  */
3884  persistence = RELPERSISTENCE_UNLOGGED;
3885  else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT)
3886  persistence = RELPERSISTENCE_PERMANENT;
3887  else
3888  persistence = rel->rd_rel->relpersistence;
3889 
3890  /* Reindex all the indexes. */
3891  doneIndexes = NIL;
3892  foreach(indexId, indexIds)
3893  {
3894  Oid indexOid = lfirst_oid(indexId);
3895 
3896  if (is_pg_class)
3897  RelationSetIndexList(rel, doneIndexes, InvalidOid);
3898 
3899  reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
3900  persistence, options);
3901 
3903 
3904  /* Index should no longer be in the pending list */
3905  Assert(!ReindexIsProcessingIndex(indexOid));
3906 
3907  if (is_pg_class)
3908  doneIndexes = lappend_oid(doneIndexes, indexOid);
3909  }
3910  }
3911  PG_CATCH();
3912  {
3913  /* Make sure list gets cleared on error exit */
3915  PG_RE_THROW();
3916  }
3917  PG_END_TRY();
3919 
3920  if (is_pg_class)
3921  RelationSetIndexList(rel, indexIds, ClassOidIndexId);
3922 
3923  /*
3924  * Close rel, but continue to hold the lock.
3925  */
3926  heap_close(rel, NoLock);
3927 
3928  result = (indexIds != NIL);
3929 
3930  /*
3931  * If the relation has a secondary toast rel, reindex that too while we
3932  * still hold the lock on the master table.
3933  */
3934  if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid))
3935  result |= reindex_relation(toast_relid, flags, options);
3936 
3937  return result;
3938 }
#define NIL
Definition: pg_list.h:69
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:172
static void SetReindexPending(List *indexes)
Definition: index.c:4027
#define RelationRelationId
Definition: pg_class.h:29
static void ResetReindexPending(void)
Definition: index.c:4055
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
#define REINDEX_REL_SUPPRESS_INDEX_USE
Definition: index.h:140
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:594
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:171
void RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
Definition: relcache.c:4580
#define NoLock
Definition: lockdefs.h:34
#define RelationGetRelationName(relation)
Definition: rel.h:445
#define ClassOidIndexId
Definition: indexing.h:112
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void CommandCounterIncrement(void)
Definition: xact.c:915
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_CATCH()
Definition: elog.h:293
#define REINDEX_REL_FORCE_INDEXES_UNLOGGED
Definition: index.h:142
#define Assert(condition)
Definition: c.h:688
#define REINDEX_REL_CHECK_CONSTRAINTS
Definition: index.h:141
#define PG_RE_THROW()
Definition: elog.h:314
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4329
void reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, int options)
Definition: index.c:3576
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ShareLock
Definition: lockdefs.h:41
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:4831
#define REINDEX_REL_FORCE_INDEXES_PERMANENT
Definition: index.h:143
#define REINDEX_REL_PROCESS_TOAST
Definition: index.h:139
#define PG_TRY()
Definition: elog.h:284
bool ReindexIsProcessingIndex(Oid indexOid)
Definition: index.c:3982
bool reindex_relation(Oid relid, int flags, int options)
Definition: index.c:3793
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:425
#define PG_END_TRY()
Definition: elog.h:300
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ ReindexIsProcessingHeap()

bool ReindexIsProcessingHeap ( Oid  heapOid)

Definition at line 3961 of file index.c.

References currentlyReindexedHeap.

Referenced by index_update_stats().

3962 {
3963  return heapOid == currentlyReindexedHeap;
3964 }
static Oid currentlyReindexedHeap
Definition: index.c:3952

◆ ReindexIsProcessingIndex()

bool ReindexIsProcessingIndex ( Oid  indexOid)

Definition at line 3982 of file index.c.

References currentlyReindexedIndex, and list_member_oid().

Referenced by reindex_relation(), systable_beginscan(), and systable_beginscan_ordered().

3983 {
3984  return indexOid == currentlyReindexedIndex ||
3986 }
static List * pendingReindexedIndexes
Definition: index.c:3954
static Oid currentlyReindexedIndex
Definition: index.c:3953
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505

◆ RestoreReindexState()

void RestoreReindexState ( void *  reindexstate)

Definition at line 4096 of file index.c.

References Assert, SerializedReindexState::currentlyReindexedHeap, currentlyReindexedHeap, SerializedReindexState::currentlyReindexedIndex, currentlyReindexedIndex, lappend_oid(), MemoryContextSwitchTo(), NIL, SerializedReindexState::numPendingReindexedIndexes, SerializedReindexState::pendingReindexedIndexes, and TopMemoryContext.

Referenced by ParallelWorkerMain().

4097 {
4098  SerializedReindexState *sistate = (SerializedReindexState *) reindexstate;
4099  int c = 0;
4100  MemoryContext oldcontext;
4101 
4104 
4107  for (c = 0; c < sistate->numPendingReindexedIndexes; ++c)
4110  sistate->pendingReindexedIndexes[c]);
4111  MemoryContextSwitchTo(oldcontext);
4112 }
#define NIL
Definition: pg_list.h:69
static Oid currentlyReindexedHeap
Definition: index.c:3952
Oid currentlyReindexedIndex
Definition: index.c:100
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static List * pendingReindexedIndexes
Definition: index.c:3954
Oid pendingReindexedIndexes[FLEXIBLE_ARRAY_MEMBER]
Definition: index.c:102
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
char * c
MemoryContext TopMemoryContext
Definition: mcxt.c:43
int numPendingReindexedIndexes
Definition: index.c:101
static Oid currentlyReindexedIndex
Definition: index.c:3953
#define Assert(condition)
Definition: c.h:688
Oid currentlyReindexedHeap
Definition: index.c:99

◆ SerializeReindexState()

void SerializeReindexState ( Size  maxsize,
char *  start_address 
)

Definition at line 4078 of file index.c.

References SerializedReindexState::currentlyReindexedHeap, currentlyReindexedHeap, SerializedReindexState::currentlyReindexedIndex, currentlyReindexedIndex, lfirst_oid, list_length(), SerializedReindexState::numPendingReindexedIndexes, and SerializedReindexState::pendingReindexedIndexes.

Referenced by InitializeParallelDSM().

4079 {
4080  SerializedReindexState *sistate = (SerializedReindexState *) start_address;
4081  int c = 0;
4082  ListCell *lc;
4083 
4087  foreach(lc, pendingReindexedIndexes)
4088  sistate->pendingReindexedIndexes[c++] = lfirst_oid(lc);
4089 }
static Oid currentlyReindexedHeap
Definition: index.c:3952
Oid currentlyReindexedIndex
Definition: index.c:100
static List * pendingReindexedIndexes
Definition: index.c:3954
Oid pendingReindexedIndexes[FLEXIBLE_ARRAY_MEMBER]
Definition: index.c:102
char * c
int numPendingReindexedIndexes
Definition: index.c:101
static Oid currentlyReindexedIndex
Definition: index.c:3953
static int list_length(const List *l)
Definition: pg_list.h:89
Oid currentlyReindexedHeap
Definition: index.c:99
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ validate_index()

void validate_index ( Oid  heapId,
Oid  indexId,
Snapshot  snapshot 
)

Definition at line 3075 of file index.c.

References IndexVacuumInfo::analyze_only, AtEOXact_GUC(), BuildIndexInfo(), DEBUG2, elog, IndexVacuumInfo::estimated_count, GetUserIdAndSecContext(), heap_close, heap_open(), v_i_state::htups, IndexInfo::ii_Concurrent, IndexVacuumInfo::index, index_bulk_delete(), index_close(), index_open(), Int8LessOperator, INT8OID, InvalidOid, v_i_state::itups, maintenance_work_mem, IndexVacuumInfo::message_level, NewGUCNestLevel(), NoLock, IndexVacuumInfo::num_heap_tuples, RelationData::rd_rel, RowExclusiveLock, SECURITY_RESTRICTED_OPERATION, SetUserIdAndSecContext(), ShareUpdateExclusiveLock, IndexVacuumInfo::strategy, v_i_state::tuplesort, tuplesort_begin_datum(), tuplesort_end(), tuplesort_performsort(), v_i_state::tups_inserted, validate_index_callback(), and validate_index_heapscan().

Referenced by DefineIndex().

3076 {
3077  Relation heapRelation,
3078  indexRelation;
3079  IndexInfo *indexInfo;
3080  IndexVacuumInfo ivinfo;
3081  v_i_state state;
3082  Oid save_userid;
3083  int save_sec_context;
3084  int save_nestlevel;
3085 
3086  /* Open and lock the parent heap relation */
3087  heapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
3088  /* And the target index relation */
3089  indexRelation = index_open(indexId, RowExclusiveLock);
3090 
3091  /*
3092  * Fetch info needed for index_insert. (You might think this should be
3093  * passed in from DefineIndex, but its copy is long gone due to having
3094  * been built in a previous transaction.)
3095  */
3096  indexInfo = BuildIndexInfo(indexRelation);
3097 
3098  /* mark build is concurrent just for consistency */
3099  indexInfo->ii_Concurrent = true;
3100 
3101  /*
3102  * Switch to the table owner's userid, so that any index functions are run
3103  * as that user. Also lock down security-restricted operations and
3104  * arrange to make GUC variable changes local to this command.
3105  */
3106  GetUserIdAndSecContext(&save_userid, &save_sec_context);
3107  SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3108  save_sec_context | SECURITY_RESTRICTED_OPERATION);
3109  save_nestlevel = NewGUCNestLevel();
3110 
3111  /*
3112  * Scan the index and gather up all the TIDs into a tuplesort object.
3113  */
3114  ivinfo.index = indexRelation;
3115  ivinfo.analyze_only = false;
3116  ivinfo.estimated_count = true;
3117  ivinfo.message_level = DEBUG2;
3118  ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
3119  ivinfo.strategy = NULL;
3120 
3121  /*
3122  * Encode TIDs as int8 values for the sort, rather than directly sorting
3123  * item pointers. This can be significantly faster, primarily because TID
3124  * is a pass-by-reference type on all platforms, whereas int8 is
3125  * pass-by-value on most platforms.
3126  */
3128  InvalidOid, false,
3130  NULL, false);
3131  state.htups = state.itups = state.tups_inserted = 0;
3132 
3133  (void) index_bulk_delete(&ivinfo, NULL,
3134  validate_index_callback, (void *) &state);
3135 
3136  /* Execute the sort */
3138 
3139  /*
3140  * Now scan the heap and "merge" it with the index
3141  */
3142  validate_index_heapscan(heapRelation,
3143  indexRelation,
3144  indexInfo,
3145  snapshot,
3146  &state);
3147 
3148  /* Done with tuplesort object */
3149  tuplesort_end(state.tuplesort);
3150 
3151  elog(DEBUG2,
3152  "validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
3153  state.htups, state.itups, state.tups_inserted);
3154 
3155  /* Roll back any GUC changes executed by index functions */
3156  AtEOXact_GUC(false, save_nestlevel);
3157 
3158  /* Restore userid and security context */
3159  SetUserIdAndSecContext(save_userid, save_sec_context);
3160 
3161  /* Close rels, but keep locks */
3162  index_close(indexRelation, NoLock);
3163  heap_close(heapRelation, NoLock);
3164 }
#define Int8LessOperator
Definition: pg_operator.h:181
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1791
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, SortCoordinate coordinate, bool randomAccess)
Definition: tuplesort.c:1100
#define SECURITY_RESTRICTED_OPERATION
Definition: miscadmin.h:295
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:396
bool analyze_only
Definition: genam.h:47
BufferAccessStrategy strategy
Definition: genam.h:51
Relation index
Definition: genam.h:46
double htups
Definition: index.c:88
#define heap_close(r, l)
Definition: heapam.h:97
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:1741
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
Tuplesortstate * tuplesort
Definition: index.c:86
#define DEBUG2
Definition: elog.h:24
static void validate_index_heapscan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, Snapshot snapshot, v_i_state *state)
Definition: index.c:3227
#define NoLock
Definition: lockdefs.h:34
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:389
#define RowExclusiveLock
Definition: lockdefs.h:38
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:5127
IndexBulkDeleteResult * index_bulk_delete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
Definition: indexam.c:744
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
int maintenance_work_mem
Definition: globals.c:114
#define INT8OID
Definition: pg_type.h:304
int message_level
Definition: genam.h:49
double num_heap_tuples
Definition: genam.h:50
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
Definition: regguts.h:298
bool ii_Concurrent
Definition: execnodes.h:160
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
double itups
Definition: index.c:88
int NewGUCNestLevel(void)
Definition: guc.c:5113
#define elog
Definition: elog.h:219
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1236
static bool validate_index_callback(ItemPointer itemptr, void *opaque)
Definition: index.c:3210
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
double tups_inserted
Definition: index.c:88
bool estimated_count
Definition: genam.h:48