PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 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 relFileNode, IndexInfo *indexInfo, List *indexColNames, Oid accessMethodObjectId, Oid tableSpaceId, Oid *collationObjectId, Oid *classObjectId, int16 *coloptions, Datum reloptions, bool isprimary, bool isconstraint, bool deferrable, bool initdeferred, bool allow_system_table_mods, bool skip_build, bool concurrent, bool is_internal, bool if_not_exists)
 
ObjectAddress index_constraint_create (Relation heapRelation, Oid indexRelationId, IndexInfo *indexInfo, const char *constraintName, char constraintType, bool deferrable, bool initdeferred, bool mark_as_primary, bool update_pgindex, bool remove_old_dependencies, bool allow_system_table_mods, bool is_internal)
 
void index_drop (Oid indexId, bool concurrent)
 
IndexInfoBuildIndexInfo (Relation index)
 
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)
 
double IndexBuildHeapScan (Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, IndexBuildCallback callback, void *callback_state)
 
double IndexBuildHeapRangeScan (Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, bool anyvisible, BlockNumber start_blockno, BlockNumber end_blockno, IndexBuildCallback callback, void *callback_state)
 
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)
 

Macro Definition Documentation

#define DEFAULT_INDEX_TYPE   "btree"

Definition at line 21 of file index.h.

Referenced by transformIndexConstraint().

#define REINDEX_REL_CHECK_CONSTRAINTS   0x04

Definition at line 124 of file index.h.

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

#define REINDEX_REL_FORCE_INDEXES_PERMANENT   0x10

Definition at line 126 of file index.h.

Referenced by finish_heap_swap(), and reindex_relation().

#define REINDEX_REL_FORCE_INDEXES_UNLOGGED   0x08

Definition at line 125 of file index.h.

Referenced by finish_heap_swap(), and reindex_relation().

#define REINDEX_REL_PROCESS_TOAST   0x01

Definition at line 122 of file index.h.

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

#define REINDEX_REL_SUPPRESS_INDEX_USE   0x02

Definition at line 123 of file index.h.

Referenced by finish_heap_swap(), and reindex_relation().

Typedef Documentation

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

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

IndexInfo* BuildIndexInfo ( Relation  index)

Definition at line 1640 of file index.c.

References CurrentMemoryContext, elog, ERROR, i, 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_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, NULL, RelationData::rd_index, RelationGetExclusionInfo(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), and RelationGetRelid.

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

1641 {
1642  IndexInfo *ii = makeNode(IndexInfo);
1643  Form_pg_index indexStruct = index->rd_index;
1644  int i;
1645  int numKeys;
1646 
1647  /* check the number of keys, and copy attr numbers into the IndexInfo */
1648  numKeys = indexStruct->indnatts;
1649  if (numKeys < 1 || numKeys > INDEX_MAX_KEYS)
1650  elog(ERROR, "invalid indnatts %d for index %u",
1651  numKeys, RelationGetRelid(index));
1652  ii->ii_NumIndexAttrs = numKeys;
1653  for (i = 0; i < numKeys; i++)
1654  ii->ii_KeyAttrNumbers[i] = indexStruct->indkey.values[i];
1655 
1656  /* fetch any expressions needed for expressional indexes */
1658  ii->ii_ExpressionsState = NIL;
1659 
1660  /* fetch index predicate if any */
1662  ii->ii_PredicateState = NULL;
1663 
1664  /* fetch exclusion constraint info if any */
1665  if (indexStruct->indisexclusion)
1666  {
1668  &ii->ii_ExclusionOps,
1669  &ii->ii_ExclusionProcs,
1670  &ii->ii_ExclusionStrats);
1671  }
1672  else
1673  {
1674  ii->ii_ExclusionOps = NULL;
1675  ii->ii_ExclusionProcs = NULL;
1676  ii->ii_ExclusionStrats = NULL;
1677  }
1678 
1679  /* other info */
1680  ii->ii_Unique = indexStruct->indisunique;
1681  ii->ii_ReadyForInserts = IndexIsReady(indexStruct);
1682  /* assume not doing speculative insertion for now */
1683  ii->ii_UniqueOps = NULL;
1684  ii->ii_UniqueProcs = NULL;
1685  ii->ii_UniqueStrats = NULL;
1686 
1687  /* initialize index-build state to default */
1688  ii->ii_Concurrent = false;
1689  ii->ii_BrokenHotChain = false;
1690 
1691  /* set up for possible use by index AM */
1692  ii->ii_AmCache = NULL;
1694 
1695  return ii;
1696 }
#define NIL
Definition: pg_list.h:69
MemoryContext ii_Context
Definition: execnodes.h:151
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition: relcache.c:5058
uint16 * ii_UniqueStrats
Definition: execnodes.h:145
List * ii_Predicate
Definition: execnodes.h:138
#define IndexIsReady(indexForm)
Definition: pg_index.h:108
ExprState * ii_PredicateState
Definition: execnodes.h:139
Oid * ii_ExclusionProcs
Definition: execnodes.h:141
Oid * ii_UniqueOps
Definition: execnodes.h:143
List * RelationGetIndexPredicate(Relation relation)
Definition: relcache.c:4768
List * ii_ExpressionsState
Definition: execnodes.h:137
Form_pg_index rd_index
Definition: rel.h:159
#define ERROR
Definition: elog.h:43
List * RelationGetIndexExpressions(Relation relation)
Definition: relcache.c:4705
Oid * ii_UniqueProcs
Definition: execnodes.h:144
bool ii_BrokenHotChain
Definition: execnodes.h:149
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
bool ii_ReadyForInserts
Definition: execnodes.h:147
void * ii_AmCache
Definition: execnodes.h:150
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
int ii_NumIndexAttrs
Definition: execnodes.h:134
bool ii_Unique
Definition: execnodes.h:146
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:229
List * ii_Expressions
Definition: execnodes.h:136
#define INDEX_MAX_KEYS
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:135
bool ii_Concurrent
Definition: execnodes.h:148
Oid * ii_ExclusionOps
Definition: execnodes.h:140
int i
#define elog
Definition: elog.h:219
uint16 * ii_ExclusionStrats
Definition: execnodes.h:142
#define RelationGetRelid(relation)
Definition: rel.h:416
void BuildSpeculativeIndexInfo ( Relation  index,
IndexInfo ii 
)

Definition at line 1711 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().

1712 {
1713  int ncols = index->rd_rel->relnatts;
1714  int i;
1715 
1716  /*
1717  * fetch info for checking unique indexes
1718  */
1719  Assert(ii->ii_Unique);
1720 
1721  if (index->rd_rel->relam != BTREE_AM_OID)
1722  elog(ERROR, "unexpected non-btree speculative unique index");
1723 
1724  ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * ncols);
1725  ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * ncols);
1726  ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * ncols);
1727 
1728  /*
1729  * We have to look up the operator's strategy number. This provides a
1730  * cross-check that the operator does match the index.
1731  */
1732  /* We need the func OIDs and strategy numbers too */
1733  for (i = 0; i < ncols; i++)
1734  {
1736  ii->ii_UniqueOps[i] =
1737  get_opfamily_member(index->rd_opfamily[i],
1738  index->rd_opcintype[i],
1739  index->rd_opcintype[i],
1740  ii->ii_UniqueStrats[i]);
1741  if (!OidIsValid(ii->ii_UniqueOps[i]))
1742  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
1743  ii->ii_UniqueStrats[i], index->rd_opcintype[i],
1744  index->rd_opcintype[i], index->rd_opfamily[i]);
1745  ii->ii_UniqueProcs[i] = get_opcode(ii->ii_UniqueOps[i]);
1746  }
1747 }
uint16 * ii_UniqueStrats
Definition: execnodes.h:145
#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:538
Oid * ii_UniqueOps
Definition: execnodes.h:143
unsigned short uint16
Definition: c.h:267
#define ERROR
Definition: elog.h:43
Oid * ii_UniqueProcs
Definition: execnodes.h:144
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:1094
bool ii_Unique
Definition: execnodes.h:146
#define Assert(condition)
Definition: c.h:675
void * palloc(Size size)
Definition: mcxt.c:849
int i
#define elog
Definition: elog.h:219
Oid * rd_opcintype
Definition: rel.h:183
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void FormIndexDatum ( IndexInfo indexInfo,
TupleTableSlot slot,
EState estate,
Datum values,
bool isnull 
)

Definition at line 1769 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, NULL, 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().

1774 {
1775  ListCell *indexpr_item;
1776  int i;
1777 
1778  if (indexInfo->ii_Expressions != NIL &&
1779  indexInfo->ii_ExpressionsState == NIL)
1780  {
1781  /* First time through, set up expression evaluation state */
1782  indexInfo->ii_ExpressionsState =
1783  ExecPrepareExprList(indexInfo->ii_Expressions, estate);
1784  /* Check caller has set up context correctly */
1785  Assert(GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
1786  }
1787  indexpr_item = list_head(indexInfo->ii_ExpressionsState);
1788 
1789  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1790  {
1791  int keycol = indexInfo->ii_KeyAttrNumbers[i];
1792  Datum iDatum;
1793  bool isNull;
1794 
1795  if (keycol != 0)
1796  {
1797  /*
1798  * Plain index column; get the value we need directly from the
1799  * heap tuple.
1800  */
1801  iDatum = slot_getattr(slot, keycol, &isNull);
1802  }
1803  else
1804  {
1805  /*
1806  * Index expression --- need to evaluate it.
1807  */
1808  if (indexpr_item == NULL)
1809  elog(ERROR, "wrong number of index expressions");
1810  iDatum = ExecEvalExprSwitchContext((ExprState *) lfirst(indexpr_item),
1811  GetPerTupleExprContext(estate),
1812  &isNull);
1813  indexpr_item = lnext(indexpr_item);
1814  }
1815  values[i] = iDatum;
1816  isnull[i] = isNull;
1817  }
1818 
1819  if (indexpr_item != NULL)
1820  elog(ERROR, "wrong number of index expressions");
1821 }
#define NIL
Definition: pg_list.h:69
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:282
#define GetPerTupleExprContext(estate)
Definition: executor.h:457
List * ii_ExpressionsState
Definition: execnodes.h:137
#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:511
uintptr_t Datum
Definition: postgres.h:372
int ii_NumIndexAttrs
Definition: execnodes.h:134
#define NULL
Definition: c.h:229
List * ii_Expressions
Definition: execnodes.h:136
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:135
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int i
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1141
#define elog
Definition: elog.h:219
void index_build ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
bool  isprimary,
bool  isreindex 
)

Definition at line 2004 of file index.c.

References IndexAmRoutine::ambuild, IndexAmRoutine::ambuildempty, Assert, AtEOXact_GUC(), CatalogTupleUpdate(), CommandCounterIncrement(), DEBUG1, EarlyPruningEnabled, elog, ereport, errmsg(), ERROR, GETSTRUCT, GetUserIdAndSecContext(), heap_close, heap_freetuple(), heap_open(), IndexBuildResult::heap_tuples, HeapTupleIsValid, IndexInfo::ii_BrokenHotChain, IndexInfo::ii_Concurrent, IndexInfo::ii_ExclusionOps, IndexBuildResult::index_tuples, index_update_stats(), IndexCheckExclusion(), IndexRelationId, INDEXRELID, INIT_FORKNUM, NewGUCNestLevel(), NULL, ObjectIdGetDatum, 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().

2009 {
2010  IndexBuildResult *stats;
2011  Oid save_userid;
2012  int save_sec_context;
2013  int save_nestlevel;
2014 
2015  /*
2016  * sanity checks
2017  */
2018  Assert(RelationIsValid(indexRelation));
2019  Assert(PointerIsValid(indexRelation->rd_amroutine));
2020  Assert(PointerIsValid(indexRelation->rd_amroutine->ambuild));
2021  Assert(PointerIsValid(indexRelation->rd_amroutine->ambuildempty));
2022 
2023  ereport(DEBUG1,
2024  (errmsg("building index \"%s\" on table \"%s\"",
2025  RelationGetRelationName(indexRelation),
2026  RelationGetRelationName(heapRelation))));
2027 
2028  /*
2029  * Switch to the table owner's userid, so that any index functions are run
2030  * as that user. Also lock down security-restricted operations and
2031  * arrange to make GUC variable changes local to this command.
2032  */
2033  GetUserIdAndSecContext(&save_userid, &save_sec_context);
2034  SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
2035  save_sec_context | SECURITY_RESTRICTED_OPERATION);
2036  save_nestlevel = NewGUCNestLevel();
2037 
2038  /*
2039  * Call the access method's build procedure
2040  */
2041  stats = indexRelation->rd_amroutine->ambuild(heapRelation, indexRelation,
2042  indexInfo);
2043  Assert(PointerIsValid(stats));
2044 
2045  /*
2046  * If this is an unlogged index, we may need to write out an init fork for
2047  * it -- but we must first check whether one already exists. If, for
2048  * example, an unlogged relation is truncated in the transaction that
2049  * created it, or truncated twice in a subsequent transaction, the
2050  * relfilenode won't change, and nothing needs to be done here.
2051  */
2052  if (indexRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
2053  !smgrexists(indexRelation->rd_smgr, INIT_FORKNUM))
2054  {
2055  RelationOpenSmgr(indexRelation);
2056  smgrcreate(indexRelation->rd_smgr, INIT_FORKNUM, false);
2057  indexRelation->rd_amroutine->ambuildempty(indexRelation);
2058  }
2059 
2060  /*
2061  * If we found any potentially broken HOT chains, mark the index as not
2062  * being usable until the current transaction is below the event horizon.
2063  * See src/backend/access/heap/README.HOT for discussion. Also set this
2064  * if early pruning/vacuuming is enabled for the heap relation. While it
2065  * might become safe to use the index earlier based on actual cleanup
2066  * activity and other active transactions, the test for that would be much
2067  * more complex and would require some form of blocking, so keep it simple
2068  * and fast by just using the current transaction.
2069  *
2070  * However, when reindexing an existing index, we should do nothing here.
2071  * Any HOT chains that are broken with respect to the index must predate
2072  * the index's original creation, so there is no need to change the
2073  * index's usability horizon. Moreover, we *must not* try to change the
2074  * index's pg_index entry while reindexing pg_index itself, and this
2075  * optimization nicely prevents that. The more complex rules needed for a
2076  * reindex are handled separately after this function returns.
2077  *
2078  * We also need not set indcheckxmin during a concurrent index build,
2079  * because we won't set indisvalid true until all transactions that care
2080  * about the broken HOT chains or early pruning/vacuuming are gone.
2081  *
2082  * Therefore, this code path can only be taken during non-concurrent
2083  * CREATE INDEX. Thus the fact that heap_update will set the pg_index
2084  * tuple's xmin doesn't matter, because that tuple was created in the
2085  * current transaction anyway. That also means we don't need to worry
2086  * about any concurrent readers of the tuple; no other transaction can see
2087  * it yet.
2088  */
2089  if ((indexInfo->ii_BrokenHotChain || EarlyPruningEnabled(heapRelation)) &&
2090  !isreindex &&
2091  !indexInfo->ii_Concurrent)
2092  {
2093  Oid indexId = RelationGetRelid(indexRelation);
2094  Relation pg_index;
2095  HeapTuple indexTuple;
2096  Form_pg_index indexForm;
2097 
2099 
2100  indexTuple = SearchSysCacheCopy1(INDEXRELID,
2101  ObjectIdGetDatum(indexId));
2102  if (!HeapTupleIsValid(indexTuple))
2103  elog(ERROR, "cache lookup failed for index %u", indexId);
2104  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
2105 
2106  /* If it's a new index, indcheckxmin shouldn't be set ... */
2107  Assert(!indexForm->indcheckxmin);
2108 
2109  indexForm->indcheckxmin = true;
2110  CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
2111 
2112  heap_freetuple(indexTuple);
2113  heap_close(pg_index, RowExclusiveLock);
2114  }
2115 
2116  /*
2117  * Update heap and index pg_class rows
2118  */
2119  index_update_stats(heapRelation,
2120  true,
2121  isprimary,
2122  stats->heap_tuples);
2123 
2124  index_update_stats(indexRelation,
2125  false,
2126  false,
2127  stats->index_tuples);
2128 
2129  /* Make the updated catalog row versions visible */
2131 
2132  /*
2133  * If it's for an exclusion constraint, make a second pass over the heap
2134  * to verify that the constraint is satisfied. We must not do this until
2135  * the index is fully valid. (Broken HOT chains shouldn't matter, though;
2136  * see comments for IndexCheckExclusion.)
2137  */
2138  if (indexInfo->ii_ExclusionOps != NULL)
2139  IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
2140 
2141  /* Roll back any GUC changes executed by index functions */
2142  AtEOXact_GUC(false, save_nestlevel);
2143 
2144  /* Restore userid and security context */
2145  SetUserIdAndSecContext(save_userid, save_sec_context);
2146 }
#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:656
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
#define SECURITY_RESTRICTED_OPERATION
Definition: miscadmin.h:295
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:396
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define IndexRelationId
Definition: pg_index.h:29
#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:1372
unsigned int Oid
Definition: postgres_ext.h:31
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:181
#define RelationOpenSmgr(relation)
Definition: rel.h:460
#define EarlyPruningEnabled(rel)
Definition: snapmgr.h:46
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ambuild_function ambuild
Definition: amapi.h:198
#define RelationIsValid(relation)
Definition: rel.h:389
ItemPointerData t_self
Definition: htup.h:65
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:5079
#define RelationGetRelationName(relation)
Definition: rel.h:436
bool ii_BrokenHotChain
Definition: execnodes.h:149
static void IndexCheckExclusion(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo)
Definition: index.c:2643
#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:922
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
bool ii_Concurrent
Definition: execnodes.h:148
static void index_update_stats(Relation rel, bool hasindex, bool isprimary, double reltuples)
Definition: index.c:1847
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
int NewGUCNestLevel(void)
Definition: guc.c:5065
Oid * ii_ExclusionOps
Definition: execnodes.h:140
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:526
#define RelationGetRelid(relation)
Definition: rel.h:416
double index_tuples
Definition: genam.h:33
double heap_tuples
Definition: genam.h:32
void index_check_primary_key ( Relation  heapRel,
IndexInfo indexInfo,
bool  is_alter_table 
)

Definition at line 192 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().

195 {
196  List *cmds;
197  int i;
198 
199  /*
200  * If ALTER TABLE, check that there isn't already a PRIMARY KEY. In CREATE
201  * TABLE, we have faith that the parser rejected multiple pkey clauses;
202  * and CREATE INDEX doesn't have a way to say PRIMARY KEY, so it's no
203  * problem either.
204  */
205  if (is_alter_table &&
206  relationHasPrimaryKey(heapRel))
207  {
208  ereport(ERROR,
209  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
210  errmsg("multiple primary keys for table \"%s\" are not allowed",
211  RelationGetRelationName(heapRel))));
212  }
213 
214  /*
215  * Check that all of the attributes in a primary key are marked as not
216  * null, otherwise attempt to ALTER TABLE .. SET NOT NULL
217  */
218  cmds = NIL;
219  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
220  {
221  AttrNumber attnum = indexInfo->ii_KeyAttrNumbers[i];
222  HeapTuple atttuple;
223  Form_pg_attribute attform;
224 
225  if (attnum == 0)
226  ereport(ERROR,
227  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
228  errmsg("primary keys cannot be expressions")));
229 
230  /* System attributes are never null, so no need to check */
231  if (attnum < 0)
232  continue;
233 
234  atttuple = SearchSysCache2(ATTNUM,
236  Int16GetDatum(attnum));
237  if (!HeapTupleIsValid(atttuple))
238  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
239  attnum, RelationGetRelid(heapRel));
240  attform = (Form_pg_attribute) GETSTRUCT(atttuple);
241 
242  if (!attform->attnotnull)
243  {
244  /* Add a subcommand to make this one NOT NULL */
246 
247  cmd->subtype = AT_SetNotNull;
248  cmd->name = pstrdup(NameStr(attform->attname));
249  cmds = lappend(cmds, cmd);
250  }
251 
252  ReleaseSysCache(atttuple);
253  }
254 
255  /*
256  * XXX: Shouldn't the ALTER TABLE .. SET NOT NULL cascade to child tables?
257  * Currently, since the PRIMARY KEY itself doesn't cascade, we don't
258  * cascade the notnull constraint(s) either; but this is pretty debatable.
259  *
260  * XXX: possible future improvement: when being called from ALTER TABLE,
261  * it would be more efficient to merge this with the outer ALTER TABLE, so
262  * as to avoid two scans. But that seems to complicate DefineIndex's API
263  * unduly.
264  */
265  if (cmds)
266  AlterTableInternal(RelationGetRelid(heapRel), cmds, false);
267 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
char * pstrdup(const char *in)
Definition: mcxt.c:1077
#define Int16GetDatum(X)
Definition: postgres.h:457
int errcode(int sqlerrcode)
Definition: elog.c:575
AlterTableType subtype
Definition: parsenodes.h:1772
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:436
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:1117
int ii_NumIndexAttrs
Definition: execnodes.h:134
static bool relationHasPrimaryKey(Relation rel)
Definition: index.c:142
#define makeNode(_type_)
Definition: nodes.h:557
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:135
void AlterTableInternal(Oid relid, List *cmds, bool recurse)
Definition: tablecmds.c:3113
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:416
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:158
ObjectAddress index_constraint_create ( Relation  heapRelation,
Oid  indexRelationId,
IndexInfo indexInfo,
const char *  constraintName,
char  constraintType,
bool  deferrable,
bool  initdeferred,
bool  mark_as_primary,
bool  update_pgindex,
bool  remove_old_dependencies,
bool  allow_system_table_mods,
bool  is_internal 
)

Definition at line 1148 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, 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_update_stats(), IndexRelationId, INDEXRELID, CreateTrigStmt::initdeferred, InvalidOid, InvokeObjectPostAlterHookArg, IsBootstrapProcessingMode, CreateTrigStmt::isconstraint, IsNormalProcessingMode, IsSystemRelation(), makeNode, NIL, NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, 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().

1160 {
1161  Oid namespaceId = RelationGetNamespace(heapRelation);
1162  ObjectAddress myself,
1163  referenced;
1164  Oid conOid;
1165 
1166  /* constraint creation support doesn't work while bootstrapping */
1168 
1169  /* enforce system-table restriction */
1170  if (!allow_system_table_mods &&
1171  IsSystemRelation(heapRelation) &&
1173  ereport(ERROR,
1174  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1175  errmsg("user-defined indexes on system catalog tables are not supported")));
1176 
1177  /* primary/unique constraints shouldn't have any expressions */
1178  if (indexInfo->ii_Expressions &&
1179  constraintType != CONSTRAINT_EXCLUSION)
1180  elog(ERROR, "constraints cannot have index expressions");
1181 
1182  /*
1183  * If we're manufacturing a constraint for a pre-existing index, we need
1184  * to get rid of the existing auto dependencies for the index (the ones
1185  * that index_create() would have made instead of calling this function).
1186  *
1187  * Note: this code would not necessarily do the right thing if the index
1188  * has any expressions or predicate, but we'd never be turning such an
1189  * index into a UNIQUE or PRIMARY KEY constraint.
1190  */
1191  if (remove_old_dependencies)
1194 
1195  /*
1196  * Construct a pg_constraint entry.
1197  */
1198  conOid = CreateConstraintEntry(constraintName,
1199  namespaceId,
1200  constraintType,
1201  deferrable,
1202  initdeferred,
1203  true,
1204  RelationGetRelid(heapRelation),
1205  indexInfo->ii_KeyAttrNumbers,
1206  indexInfo->ii_NumIndexAttrs,
1207  InvalidOid, /* no domain */
1208  indexRelationId, /* index OID */
1209  InvalidOid, /* no foreign key */
1210  NULL,
1211  NULL,
1212  NULL,
1213  NULL,
1214  0,
1215  ' ',
1216  ' ',
1217  ' ',
1218  indexInfo->ii_ExclusionOps,
1219  NULL, /* no check constraint */
1220  NULL,
1221  NULL,
1222  true, /* islocal */
1223  0, /* inhcount */
1224  true, /* noinherit */
1225  is_internal);
1226 
1227  /*
1228  * Register the index as internally dependent on the constraint.
1229  *
1230  * Note that the constraint has a dependency on the table, so we don't
1231  * need (or want) any direct dependency from the index to the table.
1232  */
1233  myself.classId = RelationRelationId;
1234  myself.objectId = indexRelationId;
1235  myself.objectSubId = 0;
1236 
1237  referenced.classId = ConstraintRelationId;
1238  referenced.objectId = conOid;
1239  referenced.objectSubId = 0;
1240 
1241  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1242 
1243  /*
1244  * If the constraint is deferrable, create the deferred uniqueness
1245  * checking trigger. (The trigger will be given an internal dependency on
1246  * the constraint by CreateTrigger.)
1247  */
1248  if (deferrable)
1249  {
1250  CreateTrigStmt *trigger;
1251 
1252  trigger = makeNode(CreateTrigStmt);
1253  trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ?
1254  "PK_ConstraintTrigger" :
1255  "Unique_ConstraintTrigger";
1256  trigger->relation = NULL;
1257  trigger->funcname = SystemFuncName("unique_key_recheck");
1258  trigger->args = NIL;
1259  trigger->row = true;
1260  trigger->timing = TRIGGER_TYPE_AFTER;
1262  trigger->columns = NIL;
1263  trigger->whenClause = NULL;
1264  trigger->isconstraint = true;
1265  trigger->deferrable = true;
1266  trigger->initdeferred = initdeferred;
1267  trigger->constrrel = NULL;
1268 
1269  (void) CreateTrigger(trigger, NULL, RelationGetRelid(heapRelation),
1270  InvalidOid, conOid, indexRelationId, true);
1271  }
1272 
1273  /*
1274  * If needed, mark the table as having a primary key. We assume it can't
1275  * have been so marked already, so no need to clear the flag in the other
1276  * case.
1277  *
1278  * Note: this might better be done by callers. We do it here to avoid
1279  * exposing index_update_stats() globally, but that wouldn't be necessary
1280  * if relhaspkey went away.
1281  */
1282  if (mark_as_primary)
1283  index_update_stats(heapRelation,
1284  true,
1285  true,
1286  -1.0);
1287 
1288  /*
1289  * If needed, mark the index as primary and/or deferred in pg_index.
1290  *
1291  * Note: When making an existing index into a constraint, caller must have
1292  * a table lock that prevents concurrent table updates; otherwise, there
1293  * is a risk that concurrent readers of the table will miss seeing this
1294  * index at all.
1295  */
1296  if (update_pgindex && (mark_as_primary || deferrable))
1297  {
1298  Relation pg_index;
1299  HeapTuple indexTuple;
1300  Form_pg_index indexForm;
1301  bool dirty = false;
1302 
1304 
1305  indexTuple = SearchSysCacheCopy1(INDEXRELID,
1306  ObjectIdGetDatum(indexRelationId));
1307  if (!HeapTupleIsValid(indexTuple))
1308  elog(ERROR, "cache lookup failed for index %u", indexRelationId);
1309  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
1310 
1311  if (mark_as_primary && !indexForm->indisprimary)
1312  {
1313  indexForm->indisprimary = true;
1314  dirty = true;
1315  }
1316 
1317  if (deferrable && indexForm->indimmediate)
1318  {
1319  indexForm->indimmediate = false;
1320  dirty = true;
1321  }
1322 
1323  if (dirty)
1324  {
1325  CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
1326 
1327  InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
1328  InvalidOid, is_internal);
1329  }
1330 
1331  heap_freetuple(indexTuple);
1332  heap_close(pg_index, RowExclusiveLock);
1333  }
1334 
1335  return referenced;
1336 }
#define NIL
Definition: pg_list.h:69
List * SystemFuncName(char *name)
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
bool IsSystemRelation(Relation relation)
Definition: catalog.c:63
Node * whenClause
Definition: parsenodes.h:2356
#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:140
#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
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
#define CONSTRAINT_PRIMARY
RangeVar * constrrel
Definition: parsenodes.h:2363
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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 InvokeObjectPostAlterHookArg(classId, objectId, subId,auxiliaryId, is_internal)
Definition: objectaccess.h:166
#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:134
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
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:557
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
List * ii_Expressions
Definition: execnodes.h:136
#define Assert(condition)
Definition: c.h:675
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:135
static void index_update_stats(Relation rel, bool hasindex, bool isprimary, double reltuples)
Definition: index.c:1847
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
Oid * ii_ExclusionOps
Definition: execnodes.h:140
int errmsg(const char *fmt,...)
Definition: elog.c:797
RangeVar * relation
Definition: parsenodes.h:2347
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define RelationGetRelid(relation)
Definition: rel.h:416
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 RelationGetNamespace(relation)
Definition: rel.h:443
Oid index_create ( Relation  heapRelation,
const char *  indexRelationName,
Oid  indexRelationId,
Oid  relFileNode,
IndexInfo indexInfo,
List indexColNames,
Oid  accessMethodObjectId,
Oid  tableSpaceId,
Oid collationObjectId,
Oid classObjectId,
int16 coloptions,
Datum  reloptions,
bool  isprimary,
bool  isconstraint,
bool  deferrable,
bool  initdeferred,
bool  allow_system_table_mods,
bool  skip_build,
bool  concurrent,
bool  is_internal,
bool  if_not_exists 
)

Definition at line 698 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_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_constraint_create(), index_register(), index_update_stats(), InitializeAttributeOids(), InsertPgClassTuple(), InvalidOid, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, IsSystemRelation(), LockRelation(), NoLock, NOTICE, NULL, ObjectAddress::objectId, ObjectAddress::objectSubId, OidIsValid, OperatorClassRelationId, RelationData::rd_indexcxt, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetNamespace, RelationGetRelid, RelationInitIndexAccessInfo(), RelationIsMapped, RelationRelationId, RELKIND_INDEX, RowExclusiveLock, and UpdateIndexRelation().

Referenced by create_toast_table(), and DefineIndex().

719 {
720  Oid heapRelationId = RelationGetRelid(heapRelation);
721  Relation pg_class;
722  Relation indexRelation;
723  TupleDesc indexTupDesc;
724  bool shared_relation;
725  bool mapped_relation;
726  bool is_exclusion;
727  Oid namespaceId;
728  int i;
729  char relpersistence;
730 
731  is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
732 
734 
735  /*
736  * The index will be in the same namespace as its parent table, and is
737  * shared across databases if and only if the parent is. Likewise, it
738  * will use the relfilenode map if and only if the parent does; and it
739  * inherits the parent's relpersistence.
740  */
741  namespaceId = RelationGetNamespace(heapRelation);
742  shared_relation = heapRelation->rd_rel->relisshared;
743  mapped_relation = RelationIsMapped(heapRelation);
744  relpersistence = heapRelation->rd_rel->relpersistence;
745 
746  /*
747  * check parameters
748  */
749  if (indexInfo->ii_NumIndexAttrs < 1)
750  elog(ERROR, "must index at least one column");
751 
752  if (!allow_system_table_mods &&
753  IsSystemRelation(heapRelation) &&
755  ereport(ERROR,
756  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
757  errmsg("user-defined indexes on system catalog tables are not supported")));
758 
759  /*
760  * concurrent index build on a system catalog is unsafe because we tend to
761  * release locks before committing in catalogs
762  */
763  if (concurrent &&
764  IsSystemRelation(heapRelation))
765  ereport(ERROR,
766  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
767  errmsg("concurrent index creation on system catalog tables is not supported")));
768 
769  /*
770  * This case is currently not supported, but there's no way to ask for it
771  * in the grammar anyway, so it can't happen.
772  */
773  if (concurrent && is_exclusion)
774  ereport(ERROR,
775  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
776  errmsg_internal("concurrent index creation for exclusion constraints is not supported")));
777 
778  /*
779  * We cannot allow indexing a shared relation after initdb (because
780  * there's no way to make the entry in other databases' pg_class).
781  */
782  if (shared_relation && !IsBootstrapProcessingMode())
783  ereport(ERROR,
784  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
785  errmsg("shared indexes cannot be created after initdb")));
786 
787  /*
788  * Shared relations must be in pg_global, too (last-ditch check)
789  */
790  if (shared_relation && tableSpaceId != GLOBALTABLESPACE_OID)
791  elog(ERROR, "shared relations must be placed in pg_global tablespace");
792 
793  if (get_relname_relid(indexRelationName, namespaceId))
794  {
795  if (if_not_exists)
796  {
797  ereport(NOTICE,
798  (errcode(ERRCODE_DUPLICATE_TABLE),
799  errmsg("relation \"%s\" already exists, skipping",
800  indexRelationName)));
801  heap_close(pg_class, RowExclusiveLock);
802  return InvalidOid;
803  }
804 
805  ereport(ERROR,
806  (errcode(ERRCODE_DUPLICATE_TABLE),
807  errmsg("relation \"%s\" already exists",
808  indexRelationName)));
809  }
810 
811  /*
812  * construct tuple descriptor for index tuples
813  */
814  indexTupDesc = ConstructTupleDescriptor(heapRelation,
815  indexInfo,
816  indexColNames,
817  accessMethodObjectId,
818  collationObjectId,
819  classObjectId);
820 
821  /*
822  * Allocate an OID for the index, unless we were told what to use.
823  *
824  * The OID will be the relfilenode as well, so make sure it doesn't
825  * collide with either pg_class OIDs or existing physical files.
826  */
827  if (!OidIsValid(indexRelationId))
828  {
829  /* Use binary-upgrade override for pg_class.oid/relfilenode? */
830  if (IsBinaryUpgrade)
831  {
833  ereport(ERROR,
834  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
835  errmsg("pg_class index OID value not set when in binary upgrade mode")));
836 
837  indexRelationId = binary_upgrade_next_index_pg_class_oid;
839  }
840  else
841  {
842  indexRelationId =
843  GetNewRelFileNode(tableSpaceId, pg_class, relpersistence);
844  }
845  }
846 
847  /*
848  * create the index relation's relcache entry and physical disk file. (If
849  * we fail further down, it's the smgr's responsibility to remove the disk
850  * file again.)
851  */
852  indexRelation = heap_create(indexRelationName,
853  namespaceId,
854  tableSpaceId,
855  indexRelationId,
856  relFileNode,
857  indexTupDesc,
859  relpersistence,
860  shared_relation,
861  mapped_relation,
862  allow_system_table_mods);
863 
864  Assert(indexRelationId == RelationGetRelid(indexRelation));
865 
866  /*
867  * Obtain exclusive lock on it. Although no other backends can see it
868  * until we commit, this prevents deadlock-risk complaints from lock
869  * manager in cases such as CLUSTER.
870  */
871  LockRelation(indexRelation, AccessExclusiveLock);
872 
873  /*
874  * Fill in fields of the index's pg_class entry that are not set correctly
875  * by heap_create.
876  *
877  * XXX should have a cleaner way to create cataloged indexes
878  */
879  indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
880  indexRelation->rd_rel->relam = accessMethodObjectId;
881  indexRelation->rd_rel->relhasoids = false;
882 
883  /*
884  * store index's pg_class entry
885  */
886  InsertPgClassTuple(pg_class, indexRelation,
887  RelationGetRelid(indexRelation),
888  (Datum) 0,
889  reloptions);
890 
891  /* done with pg_class */
892  heap_close(pg_class, RowExclusiveLock);
893 
894  /*
895  * now update the object id's of all the attribute tuple forms in the
896  * index relation's tuple descriptor
897  */
898  InitializeAttributeOids(indexRelation,
899  indexInfo->ii_NumIndexAttrs,
900  indexRelationId);
901 
902  /*
903  * append ATTRIBUTE tuples for the index
904  */
905  AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs);
906 
907  /* ----------------
908  * update pg_index
909  * (append INDEX tuple)
910  *
911  * Note that this stows away a representation of "predicate".
912  * (Or, could define a rule to maintain the predicate) --Nels, Feb '92
913  * ----------------
914  */
915  UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo,
916  collationObjectId, classObjectId, coloptions,
917  isprimary, is_exclusion,
918  !deferrable,
919  !concurrent);
920 
921  /*
922  * Register constraint and dependencies for the index.
923  *
924  * If the index is from a CONSTRAINT clause, construct a pg_constraint
925  * entry. The index will be linked to the constraint, which in turn is
926  * linked to the table. If it's not a CONSTRAINT, we need to make a
927  * dependency directly on the table.
928  *
929  * We don't need a dependency on the namespace, because there'll be an
930  * indirect dependency via our parent table.
931  *
932  * During bootstrap we can't register any dependencies, and we don't try
933  * to make a constraint either.
934  */
936  {
937  ObjectAddress myself,
938  referenced;
939 
940  myself.classId = RelationRelationId;
941  myself.objectId = indexRelationId;
942  myself.objectSubId = 0;
943 
944  if (isconstraint)
945  {
946  char constraintType;
947 
948  if (isprimary)
949  constraintType = CONSTRAINT_PRIMARY;
950  else if (indexInfo->ii_Unique)
951  constraintType = CONSTRAINT_UNIQUE;
952  else if (is_exclusion)
953  constraintType = CONSTRAINT_EXCLUSION;
954  else
955  {
956  elog(ERROR, "constraint must be PRIMARY, UNIQUE or EXCLUDE");
957  constraintType = 0; /* keep compiler quiet */
958  }
959 
960  index_constraint_create(heapRelation,
961  indexRelationId,
962  indexInfo,
963  indexRelationName,
964  constraintType,
965  deferrable,
966  initdeferred,
967  false, /* already marked primary */
968  false, /* pg_index entry is OK */
969  false, /* no old dependencies */
970  allow_system_table_mods,
971  is_internal);
972  }
973  else
974  {
975  bool have_simple_col = false;
976 
977  /* Create auto dependencies on simply-referenced columns */
978  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
979  {
980  if (indexInfo->ii_KeyAttrNumbers[i] != 0)
981  {
982  referenced.classId = RelationRelationId;
983  referenced.objectId = heapRelationId;
984  referenced.objectSubId = indexInfo->ii_KeyAttrNumbers[i];
985 
986  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
987 
988  have_simple_col = true;
989  }
990  }
991 
992  /*
993  * If there are no simply-referenced columns, give the index an
994  * auto dependency on the whole table. In most cases, this will
995  * be redundant, but it might not be if the index expressions and
996  * predicate contain no Vars or only whole-row Vars.
997  */
998  if (!have_simple_col)
999  {
1000  referenced.classId = RelationRelationId;
1001  referenced.objectId = heapRelationId;
1002  referenced.objectSubId = 0;
1003 
1004  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1005  }
1006 
1007  /* Non-constraint indexes can't be deferrable */
1008  Assert(!deferrable);
1009  Assert(!initdeferred);
1010  }
1011 
1012  /* Store dependency on collations */
1013  /* The default collation is pinned, so don't bother recording it */
1014  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1015  {
1016  if (OidIsValid(collationObjectId[i]) &&
1017  collationObjectId[i] != DEFAULT_COLLATION_OID)
1018  {
1019  referenced.classId = CollationRelationId;
1020  referenced.objectId = collationObjectId[i];
1021  referenced.objectSubId = 0;
1022 
1023  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1024  }
1025  }
1026 
1027  /* Store dependency on operator classes */
1028  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1029  {
1030  referenced.classId = OperatorClassRelationId;
1031  referenced.objectId = classObjectId[i];
1032  referenced.objectSubId = 0;
1033 
1034  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1035  }
1036 
1037  /* Store dependencies on anything mentioned in index expressions */
1038  if (indexInfo->ii_Expressions)
1039  {
1041  (Node *) indexInfo->ii_Expressions,
1042  heapRelationId,
1044  DEPENDENCY_AUTO, false);
1045  }
1046 
1047  /* Store dependencies on anything mentioned in predicate */
1048  if (indexInfo->ii_Predicate)
1049  {
1051  (Node *) indexInfo->ii_Predicate,
1052  heapRelationId,
1054  DEPENDENCY_AUTO, false);
1055  }
1056  }
1057  else
1058  {
1059  /* Bootstrap mode - assert we weren't asked for constraint support */
1060  Assert(!isconstraint);
1061  Assert(!deferrable);
1062  Assert(!initdeferred);
1063  }
1064 
1065  /* Post creation hook for new index */
1067  indexRelationId, 0, is_internal);
1068 
1069  /*
1070  * Advance the command counter so that we can see the newly-entered
1071  * catalog tuples for the index.
1072  */
1074 
1075  /*
1076  * In bootstrap mode, we have to fill in the index strategy structure with
1077  * information from the catalogs. If we aren't bootstrapping, then the
1078  * relcache entry has already been rebuilt thanks to sinval update during
1079  * CommandCounterIncrement.
1080  */
1082  RelationInitIndexAccessInfo(indexRelation);
1083  else
1084  Assert(indexRelation->rd_indexcxt != NULL);
1085 
1086  /*
1087  * If this is bootstrap (initdb) time, then we don't actually fill in the
1088  * index yet. We'll be creating more indexes and classes later, so we
1089  * delay filling them in until just before we're done with bootstrapping.
1090  * Similarly, if the caller specified skip_build then filling the index is
1091  * delayed till later (ALTER TABLE can save work in some cases with this).
1092  * Otherwise, we call the AM routine that constructs the index.
1093  */
1095  {
1096  index_register(heapRelationId, indexRelationId, indexInfo);
1097  }
1098  else if (skip_build)
1099  {
1100  /*
1101  * Caller is responsible for filling the index later on. However,
1102  * we'd better make sure that the heap relation is correctly marked as
1103  * having an index.
1104  */
1105  index_update_stats(heapRelation,
1106  true,
1107  isprimary,
1108  -1.0);
1109  /* Make the above update visible */
1111  }
1112  else
1113  {
1114  index_build(heapRelation, indexRelation, indexInfo, isprimary, false);
1115  }
1116 
1117  /*
1118  * Close the index; but we keep the lock that we acquired above until end
1119  * of transaction. Closing the heap is caller's responsibility.
1120  */
1121  index_close(indexRelation, NoLock);
1122 
1123  return indexRelationId;
1124 }
List * ii_Predicate
Definition: execnodes.h:138
bool IsSystemRelation(Relation relation)
Definition: catalog.c:63
#define RelationRelationId
Definition: pg_class.h:29
static void InitializeAttributeOids(Relation indexRelation, int numatts, Oid indexoid)
Definition: index.c:489
Oid binary_upgrade_next_index_pg_class_oid
Definition: index.c:77
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
Definition: nodes.h:509
#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
#define CONSTRAINT_UNIQUE
#define OidIsValid(objectId)
Definition: c.h:538
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:764
static void UpdateIndexRelation(Oid indexoid, Oid heapoid, IndexInfo *indexInfo, Oid *collationOids, Oid *classOids, int16 *coloptions, bool primary, bool isexclusion, bool immediate, bool isvalid)
Definition: index.c:550
#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:1683
#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:275
void index_register(Oid heap, Oid ind, IndexInfo *indexInfo)
Definition: bootstrap.c:1066
#define ereport(elevel, rest)
Definition: elog.h:122
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isprimary, bool isreindex)
Definition: index.c:2004
static void AppendAttributeTuples(Relation indexRelation, int numatts)
Definition: index.c:507
#define RelationIsMapped(relation)
Definition: rel.h:453
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:922
int ii_NumIndexAttrs
Definition: execnodes.h:134
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:147
#define CollationRelationId
Definition: pg_collation.h:30
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
bool ii_Unique
Definition: execnodes.h:146
#define NULL
Definition: c.h:229
List * ii_Expressions
Definition: execnodes.h:136
#define Assert(condition)
Definition: c.h:675
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:395
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:135
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool ignore_self)
Definition: dependency.c:1392
static void index_update_stats(Relation rel, bool hasindex, bool isprimary, double reltuples)
Definition: index.c:1847
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
void RelationInitIndexAccessInfo(Relation relation)
Definition: relcache.c:1509
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
#define AccessExclusiveLock
Definition: lockdefs.h:45
Oid * ii_ExclusionOps
Definition: execnodes.h:140
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
ObjectAddress index_constraint_create(Relation heapRelation, Oid indexRelationId, IndexInfo *indexInfo, const char *constraintName, char constraintType, bool deferrable, bool initdeferred, bool mark_as_primary, bool update_pgindex, bool remove_old_dependencies, bool allow_system_table_mods, bool is_internal)
Definition: index.c:1148
#define elog
Definition: elog.h:219
#define RelationGetRelid(relation)
Definition: rel.h:416
#define RelationGetNamespace(relation)
Definition: rel.h:443
void index_drop ( Oid  indexId,
bool  concurrent 
)

Definition at line 1345 of file index.c.

References AccessExclusiveLock, Anum_pg_index_indexprs, CacheInvalidateRelcache(), CatalogTupleDelete(), CheckTableNotInUse(), CommitTransactionCommand(), LockRelId::dbId, DeleteAttributeTuples(), 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, InvalidTransactionId, LockRelationIdForSession(), LockInfoData::lockRelId, NoLock, ObjectIdGetDatum, PopActiveSnapshot(), RelationData::rd_lockInfo, RelationDropStorage(), RelationForgetRelation(), ReleaseSysCache(), LockRelId::relId, RemoveStatistics(), RowExclusiveLock, SearchSysCache1, SET_LOCKTAG_RELATION, ShareUpdateExclusiveLock, StartTransactionCommand(), HeapTupleData::t_self, TransferPredicateLocksToHeapRelation(), UnlockRelationIdForSession(), and WaitForLockers().

Referenced by doDeletion().

1346 {
1347  Oid heapId;
1348  Relation userHeapRelation;
1349  Relation userIndexRelation;
1350  Relation indexRelation;
1351  HeapTuple tuple;
1352  bool hasexprs;
1353  LockRelId heaprelid,
1354  indexrelid;
1355  LOCKTAG heaplocktag;
1356  LOCKMODE lockmode;
1357 
1358  /*
1359  * To drop an index safely, we must grab exclusive lock on its parent
1360  * table. Exclusive lock on the index alone is insufficient because
1361  * another backend might be about to execute a query on the parent table.
1362  * If it relies on a previously cached list of index OIDs, then it could
1363  * attempt to access the just-dropped index. We must therefore take a
1364  * table lock strong enough to prevent all queries on the table from
1365  * proceeding until we commit and send out a shared-cache-inval notice
1366  * that will make them update their index lists.
1367  *
1368  * In the concurrent case we avoid this requirement by disabling index use
1369  * in multiple steps and waiting out any transactions that might be using
1370  * the index, so we don't need exclusive lock on the parent table. Instead
1371  * we take ShareUpdateExclusiveLock, to ensure that two sessions aren't
1372  * doing CREATE/DROP INDEX CONCURRENTLY on the same index. (We will get
1373  * AccessExclusiveLock on the index below, once we're sure nobody else is
1374  * using it.)
1375  */
1376  heapId = IndexGetRelation(indexId, false);
1377  lockmode = concurrent ? ShareUpdateExclusiveLock : AccessExclusiveLock;
1378  userHeapRelation = heap_open(heapId, lockmode);
1379  userIndexRelation = index_open(indexId, lockmode);
1380 
1381  /*
1382  * We might still have open queries using it in our own session, which the
1383  * above locking won't prevent, so test explicitly.
1384  */
1385  CheckTableNotInUse(userIndexRelation, "DROP INDEX");
1386 
1387  /*
1388  * Drop Index Concurrently is more or less the reverse process of Create
1389  * Index Concurrently.
1390  *
1391  * First we unset indisvalid so queries starting afterwards don't use the
1392  * index to answer queries anymore. We have to keep indisready = true so
1393  * transactions that are still scanning the index can continue to see
1394  * valid index contents. For instance, if they are using READ COMMITTED
1395  * mode, and another transaction makes changes and commits, they need to
1396  * see those new tuples in the index.
1397  *
1398  * After all transactions that could possibly have used the index for
1399  * queries end, we can unset indisready and indislive, then wait till
1400  * nobody could be touching it anymore. (Note: we need indislive because
1401  * this state must be distinct from the initial state during CREATE INDEX
1402  * CONCURRENTLY, which has indislive true while indisready and indisvalid
1403  * are false. That's because in that state, transactions must examine the
1404  * index for HOT-safety decisions, while in this state we don't want them
1405  * to open it at all.)
1406  *
1407  * Since all predicate locks on the index are about to be made invalid, we
1408  * must promote them to predicate locks on the heap. In the
1409  * non-concurrent case we can just do that now. In the concurrent case
1410  * it's a bit trickier. The predicate locks must be moved when there are
1411  * no index scans in progress on the index and no more can subsequently
1412  * start, so that no new predicate locks can be made on the index. Also,
1413  * they must be moved before heap inserts stop maintaining the index, else
1414  * the conflict with the predicate lock on the index gap could be missed
1415  * before the lock on the heap relation is in place to detect a conflict
1416  * based on the heap tuple insert.
1417  */
1418  if (concurrent)
1419  {
1420  /*
1421  * We must commit our transaction in order to make the first pg_index
1422  * state update visible to other sessions. If the DROP machinery has
1423  * already performed any other actions (removal of other objects,
1424  * pg_depend entries, etc), the commit would make those actions
1425  * permanent, which would leave us with inconsistent catalog state if
1426  * we fail partway through the following sequence. Since DROP INDEX
1427  * CONCURRENTLY is restricted to dropping just one index that has no
1428  * dependencies, we should get here before anything's been done ---
1429  * but let's check that to be sure. We can verify that the current
1430  * transaction has not executed any transactional updates by checking
1431  * that no XID has been assigned.
1432  */
1434  ereport(ERROR,
1435  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1436  errmsg("DROP INDEX CONCURRENTLY must be first action in transaction")));
1437 
1438  /*
1439  * Mark index invalid by updating its pg_index entry
1440  */
1442 
1443  /*
1444  * Invalidate the relcache for the table, so that after this commit
1445  * all sessions will refresh any cached plans that might reference the
1446  * index.
1447  */
1448  CacheInvalidateRelcache(userHeapRelation);
1449 
1450  /* save lockrelid and locktag for below, then close but keep locks */
1451  heaprelid = userHeapRelation->rd_lockInfo.lockRelId;
1452  SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
1453  indexrelid = userIndexRelation->rd_lockInfo.lockRelId;
1454 
1455  heap_close(userHeapRelation, NoLock);
1456  index_close(userIndexRelation, NoLock);
1457 
1458  /*
1459  * We must commit our current transaction so that the indisvalid
1460  * update becomes visible to other transactions; then start another.
1461  * Note that any previously-built data structures are lost in the
1462  * commit. The only data we keep past here are the relation IDs.
1463  *
1464  * Before committing, get a session-level lock on the table, to ensure
1465  * that neither it nor the index can be dropped before we finish. This
1466  * cannot block, even if someone else is waiting for access, because
1467  * we already have the same lock within our transaction.
1468  */
1471 
1475 
1476  /*
1477  * Now we must wait until no running transaction could be using the
1478  * index for a query. Use AccessExclusiveLock here to check for
1479  * running transactions that hold locks of any kind on the table. Note
1480  * we do not need to worry about xacts that open the table for reading
1481  * after this point; they will see the index as invalid when they open
1482  * the relation.
1483  *
1484  * Note: the reason we use actual lock acquisition here, rather than
1485  * just checking the ProcArray and sleeping, is that deadlock is
1486  * possible if one of the transactions in question is blocked trying
1487  * to acquire an exclusive lock on our table. The lock code will
1488  * detect deadlock and error out properly.
1489  */
1490  WaitForLockers(heaplocktag, AccessExclusiveLock);
1491 
1492  /*
1493  * No more predicate locks will be acquired on this index, and we're
1494  * about to stop doing inserts into the index which could show
1495  * conflicts with existing predicate locks, so now is the time to move
1496  * them to the heap relation.
1497  */
1498  userHeapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
1499  userIndexRelation = index_open(indexId, ShareUpdateExclusiveLock);
1500  TransferPredicateLocksToHeapRelation(userIndexRelation);
1501 
1502  /*
1503  * Now we are sure that nobody uses the index for queries; they just
1504  * might have it open for updating it. So now we can unset indisready
1505  * and indislive, then wait till nobody could be using it at all
1506  * anymore.
1507  */
1509 
1510  /*
1511  * Invalidate the relcache for the table, so that after this commit
1512  * all sessions will refresh the table's index list. Forgetting just
1513  * the index's relcache entry is not enough.
1514  */
1515  CacheInvalidateRelcache(userHeapRelation);
1516 
1517  /*
1518  * Close the relations again, though still holding session lock.
1519  */
1520  heap_close(userHeapRelation, NoLock);
1521  index_close(userIndexRelation, NoLock);
1522 
1523  /*
1524  * Again, commit the transaction to make the pg_index update visible
1525  * to other sessions.
1526  */
1529 
1530  /*
1531  * Wait till every transaction that saw the old index state has
1532  * finished.
1533  */
1534  WaitForLockers(heaplocktag, AccessExclusiveLock);
1535 
1536  /*
1537  * Re-open relations to allow us to complete our actions.
1538  *
1539  * At this point, nothing should be accessing the index, but lets
1540  * leave nothing to chance and grab AccessExclusiveLock on the index
1541  * before the physical deletion.
1542  */
1543  userHeapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
1544  userIndexRelation = index_open(indexId, AccessExclusiveLock);
1545  }
1546  else
1547  {
1548  /* Not concurrent, so just transfer predicate locks and we're good */
1549  TransferPredicateLocksToHeapRelation(userIndexRelation);
1550  }
1551 
1552  /*
1553  * Schedule physical removal of the files
1554  */
1555  RelationDropStorage(userIndexRelation);
1556 
1557  /*
1558  * Close and flush the index's relcache entry, to ensure relcache doesn't
1559  * try to rebuild it while we're deleting catalog entries. We keep the
1560  * lock though.
1561  */
1562  index_close(userIndexRelation, NoLock);
1563 
1564  RelationForgetRelation(indexId);
1565 
1566  /*
1567  * fix INDEX relation, and check for expressional index
1568  */
1569  indexRelation = heap_open(IndexRelationId, RowExclusiveLock);
1570 
1571  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
1572  if (!HeapTupleIsValid(tuple))
1573  elog(ERROR, "cache lookup failed for index %u", indexId);
1574 
1575  hasexprs = !heap_attisnull(tuple, Anum_pg_index_indexprs);
1576 
1577  CatalogTupleDelete(indexRelation, &tuple->t_self);
1578 
1579  ReleaseSysCache(tuple);
1580  heap_close(indexRelation, RowExclusiveLock);
1581 
1582  /*
1583  * if it has any expression columns, we might have stored statistics about
1584  * them.
1585  */
1586  if (hasexprs)
1587  RemoveStatistics(indexId, 0);
1588 
1589  /*
1590  * fix ATTRIBUTE relation
1591  */
1592  DeleteAttributeTuples(indexId);
1593 
1594  /*
1595  * fix RELATION relation
1596  */
1597  DeleteRelationTuple(indexId);
1598 
1599  /*
1600  * We are presently too lazy to attempt to compute the new correct value
1601  * of relhasindex (the next VACUUM will fix it if necessary). So there is
1602  * no need to update the pg_class tuple for the owning relation. But we
1603  * must send out a shared-cache-inval notice on the owning relation to
1604  * ensure other backends update their relcache lists of indexes. (In the
1605  * concurrent case, this is redundant but harmless.)
1606  */
1607  CacheInvalidateRelcache(userHeapRelation);
1608 
1609  /*
1610  * Close owning rel, but keep lock
1611  */
1612  heap_close(userHeapRelation, NoLock);
1613 
1614  /*
1615  * Release the session locks before we go.
1616  */
1617  if (concurrent)
1618  {
1621  }
1622 }
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3279
LockRelId lockRelId
Definition: rel.h:44
int LOCKMODE
Definition: lockdefs.h:26
void index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
Definition: index.c:3200
#define IndexRelationId
Definition: pg_index.h:29
void CommitTransactionCommand(void)
Definition: xact.c:2748
Oid dbId
Definition: rel.h:39
Definition: lock.h:178
int errcode(int sqlerrcode)
Definition: elog.c:575
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2684
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
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:312
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:297
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3010
#define ereport(elevel, rest)
Definition: elog.h:122
void TransferPredicateLocksToHeapRelation(Relation relation)
Definition: predicate.c:3088
void RelationDropStorage(Relation rel)
Definition: storage.c:145
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode)
Definition: lmgr.c:811
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1434
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void StartTransactionCommand(void)
Definition: xact.c:2678
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1463
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:2744
#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
void index_set_state_flags ( Oid  indexId,
IndexStateFlagsAction  action 
)

Definition at line 3200 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().

3201 {
3202  Relation pg_index;
3203  HeapTuple indexTuple;
3204  Form_pg_index indexForm;
3205 
3206  /* Assert that current xact hasn't done any transactional updates */
3208 
3209  /* Open pg_index and fetch a writable copy of the index's tuple */
3211 
3212  indexTuple = SearchSysCacheCopy1(INDEXRELID,
3213  ObjectIdGetDatum(indexId));
3214  if (!HeapTupleIsValid(indexTuple))
3215  elog(ERROR, "cache lookup failed for index %u", indexId);
3216  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
3217 
3218  /* Perform the requested state change on the copy */
3219  switch (action)
3220  {
3222  /* Set indisready during a CREATE INDEX CONCURRENTLY sequence */
3223  Assert(indexForm->indislive);
3224  Assert(!indexForm->indisready);
3225  Assert(!indexForm->indisvalid);
3226  indexForm->indisready = true;
3227  break;
3229  /* Set indisvalid during a CREATE INDEX CONCURRENTLY sequence */
3230  Assert(indexForm->indislive);
3231  Assert(indexForm->indisready);
3232  Assert(!indexForm->indisvalid);
3233  indexForm->indisvalid = true;
3234  break;
3236 
3237  /*
3238  * Clear indisvalid during a DROP INDEX CONCURRENTLY sequence
3239  *
3240  * If indisready == true we leave it set so the index still gets
3241  * maintained by active transactions. We only need to ensure that
3242  * indisvalid is false. (We don't assert that either is initially
3243  * true, though, since we want to be able to retry a DROP INDEX
3244  * CONCURRENTLY that failed partway through.)
3245  *
3246  * Note: the CLUSTER logic assumes that indisclustered cannot be
3247  * set on any invalid index, so clear that flag too.
3248  */
3249  indexForm->indisvalid = false;
3250  indexForm->indisclustered = false;
3251  break;
3252  case INDEX_DROP_SET_DEAD:
3253 
3254  /*
3255  * Clear indisready/indislive during DROP INDEX CONCURRENTLY
3256  *
3257  * We clear both indisready and indislive, because we not only
3258  * want to stop updates, we want to prevent sessions from touching
3259  * the index at all.
3260  */
3261  Assert(!indexForm->indisvalid);
3262  indexForm->indisready = false;
3263  indexForm->indislive = false;
3264  break;
3265  }
3266 
3267  /* ... and write it back in-place */
3268  heap_inplace_update(pg_index, indexTuple);
3269 
3270  heap_close(pg_index, RowExclusiveLock);
3271 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define IndexRelationId
Definition: pg_index.h:29
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:675
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
void heap_inplace_update(Relation relation, HeapTuple tuple)
Definition: heapam.c:6195
#define elog
Definition: elog.h:219
double IndexBuildHeapRangeScan ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
bool  allow_sync,
bool  anyvisible,
BlockNumber  start_blockno,
BlockNumber  end_blockno,
IndexBuildCallback  callback,
void *  callback_state 
)

Definition at line 2198 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, IsSystemRelation(), ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, ItemPointerSetOffsetNumber, LockBuffer(), MakeSingleTupleTableSlot(), MaxHeapTuplesPerPage, MemoryContextReset(), NIL, NULL, OffsetNumberIsValid, OidIsValid, OldestXmin, PROCARRAY_FLAGS_VACUUM, RelationData::rd_rel, RegisterSnapshot(), RelationGetDescr, RelationGetRelationName, HeapScanDescData::rs_cblock, HeapScanDescData::rs_cbuf, SnapshotAny, HeapTupleData::t_data, HeapTupleData::t_self, TransactionIdIsCurrentTransactionId(), UnregisterSnapshot(), values, WARNING, XactLockTableWait(), and XLTW_InsertIndexUnique.

Referenced by IndexBuildHeapScan(), and summarize_range().

2207 {
2208  bool is_system_catalog;
2209  bool checking_uniqueness;
2210  HeapScanDesc scan;
2211  HeapTuple heapTuple;
2213  bool isnull[INDEX_MAX_KEYS];
2214  double reltuples;
2215  ExprState *predicate;
2216  TupleTableSlot *slot;
2217  EState *estate;
2218  ExprContext *econtext;
2219  Snapshot snapshot;
2221  BlockNumber root_blkno = InvalidBlockNumber;
2222  OffsetNumber root_offsets[MaxHeapTuplesPerPage];
2223 
2224  /*
2225  * sanity checks
2226  */
2227  Assert(OidIsValid(indexRelation->rd_rel->relam));
2228 
2229  /* Remember if it's a system catalog */
2230  is_system_catalog = IsSystemRelation(heapRelation);
2231 
2232  /* See whether we're verifying uniqueness/exclusion properties */
2233  checking_uniqueness = (indexInfo->ii_Unique ||
2234  indexInfo->ii_ExclusionOps != NULL);
2235 
2236  /*
2237  * "Any visible" mode is not compatible with uniqueness checks; make sure
2238  * only one of those is requested.
2239  */
2240  Assert(!(anyvisible && checking_uniqueness));
2241 
2242  /*
2243  * Need an EState for evaluation of index expressions and partial-index
2244  * predicates. Also a slot to hold the current tuple.
2245  */
2246  estate = CreateExecutorState();
2247  econtext = GetPerTupleExprContext(estate);
2248  slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
2249 
2250  /* Arrange for econtext's scan tuple to be the tuple under test */
2251  econtext->ecxt_scantuple = slot;
2252 
2253  /* Set up execution state for predicate, if any. */
2254  predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
2255 
2256  /*
2257  * Prepare for scan of the base relation. In a normal index build, we use
2258  * SnapshotAny because we must retrieve all tuples and do our own time
2259  * qual checks (because we have to index RECENTLY_DEAD tuples). In a
2260  * concurrent build, or during bootstrap, we take a regular MVCC snapshot
2261  * and index whatever's live according to that.
2262  */
2263  if (IsBootstrapProcessingMode() || indexInfo->ii_Concurrent)
2264  {
2266  OldestXmin = InvalidTransactionId; /* not used */
2267 
2268  /* "any visible" mode is not compatible with this */
2269  Assert(!anyvisible);
2270  }
2271  else
2272  {
2273  snapshot = SnapshotAny;
2274  /* okay to ignore lazy VACUUMs here */
2275  OldestXmin = GetOldestXmin(heapRelation, PROCARRAY_FLAGS_VACUUM);
2276  }
2277 
2278  scan = heap_beginscan_strat(heapRelation, /* relation */
2279  snapshot, /* snapshot */
2280  0, /* number of keys */
2281  NULL, /* scan key */
2282  true, /* buffer access strategy OK */
2283  allow_sync); /* syncscan OK? */
2284 
2285  /* set our scan endpoints */
2286  if (!allow_sync)
2287  heap_setscanlimits(scan, start_blockno, numblocks);
2288  else
2289  {
2290  /* syncscan can only be requested on whole relation */
2291  Assert(start_blockno == 0);
2292  Assert(numblocks == InvalidBlockNumber);
2293  }
2294 
2295  reltuples = 0;
2296 
2297  /*
2298  * Scan all tuples in the base relation.
2299  */
2300  while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2301  {
2302  bool tupleIsAlive;
2303 
2305 
2306  /*
2307  * When dealing with a HOT-chain of updated tuples, we want to index
2308  * the values of the live tuple (if any), but index it under the TID
2309  * of the chain's root tuple. This approach is necessary to preserve
2310  * the HOT-chain structure in the heap. So we need to be able to find
2311  * the root item offset for every tuple that's in a HOT-chain. When
2312  * first reaching a new page of the relation, call
2313  * heap_get_root_tuples() to build a map of root item offsets on the
2314  * page.
2315  *
2316  * It might look unsafe to use this information across buffer
2317  * lock/unlock. However, we hold ShareLock on the table so no
2318  * ordinary insert/update/delete should occur; and we hold pin on the
2319  * buffer continuously while visiting the page, so no pruning
2320  * operation can occur either.
2321  *
2322  * Also, although our opinions about tuple liveness could change while
2323  * we scan the page (due to concurrent transaction commits/aborts),
2324  * the chain root locations won't, so this info doesn't need to be
2325  * rebuilt after waiting for another transaction.
2326  *
2327  * Note the implied assumption that there is no more than one live
2328  * tuple per HOT-chain --- else we could create more than one index
2329  * entry pointing to the same root tuple.
2330  */
2331  if (scan->rs_cblock != root_blkno)
2332  {
2333  Page page = BufferGetPage(scan->rs_cbuf);
2334 
2336  heap_get_root_tuples(page, root_offsets);
2338 
2339  root_blkno = scan->rs_cblock;
2340  }
2341 
2342  if (snapshot == SnapshotAny)
2343  {
2344  /* do our own time qual check */
2345  bool indexIt;
2346  TransactionId xwait;
2347 
2348  recheck:
2349 
2350  /*
2351  * We could possibly get away with not locking the buffer here,
2352  * since caller should hold ShareLock on the relation, but let's
2353  * be conservative about it. (This remark is still correct even
2354  * with HOT-pruning: our pin on the buffer prevents pruning.)
2355  */
2357 
2358  switch (HeapTupleSatisfiesVacuum(heapTuple, OldestXmin,
2359  scan->rs_cbuf))
2360  {
2361  case HEAPTUPLE_DEAD:
2362  /* Definitely dead, we can ignore it */
2363  indexIt = false;
2364  tupleIsAlive = false;
2365  break;
2366  case HEAPTUPLE_LIVE:
2367  /* Normal case, index and unique-check it */
2368  indexIt = true;
2369  tupleIsAlive = true;
2370  break;
2372 
2373  /*
2374  * If tuple is recently deleted then we must index it
2375  * anyway to preserve MVCC semantics. (Pre-existing
2376  * transactions could try to use the index after we finish
2377  * building it, and may need to see such tuples.)
2378  *
2379  * However, if it was HOT-updated then we must only index
2380  * the live tuple at the end of the HOT-chain. Since this
2381  * breaks semantics for pre-existing snapshots, mark the
2382  * index as unusable for them.
2383  */
2384  if (HeapTupleIsHotUpdated(heapTuple))
2385  {
2386  indexIt = false;
2387  /* mark the index as unsafe for old snapshots */
2388  indexInfo->ii_BrokenHotChain = true;
2389  }
2390  else
2391  indexIt = true;
2392  /* In any case, exclude the tuple from unique-checking */
2393  tupleIsAlive = false;
2394  break;
2396 
2397  /*
2398  * In "anyvisible" mode, this tuple is visible and we
2399  * don't need any further checks.
2400  */
2401  if (anyvisible)
2402  {
2403  indexIt = true;
2404  tupleIsAlive = true;
2405  break;
2406  }
2407 
2408  /*
2409  * Since caller should hold ShareLock or better, normally
2410  * the only way to see this is if it was inserted earlier
2411  * in our own transaction. However, it can happen in
2412  * system catalogs, since we tend to release write lock
2413  * before commit there. Give a warning if neither case
2414  * applies.
2415  */
2416  xwait = HeapTupleHeaderGetXmin(heapTuple->t_data);
2418  {
2419  if (!is_system_catalog)
2420  elog(WARNING, "concurrent insert in progress within table \"%s\"",
2421  RelationGetRelationName(heapRelation));
2422 
2423  /*
2424  * If we are performing uniqueness checks, indexing
2425  * such a tuple could lead to a bogus uniqueness
2426  * failure. In that case we wait for the inserting
2427  * transaction to finish and check again.
2428  */
2429  if (checking_uniqueness)
2430  {
2431  /*
2432  * Must drop the lock on the buffer before we wait
2433  */
2435  XactLockTableWait(xwait, heapRelation,
2436  &heapTuple->t_self,
2439  goto recheck;
2440  }
2441  }
2442 
2443  /*
2444  * We must index such tuples, since if the index build
2445  * commits then they're good.
2446  */
2447  indexIt = true;
2448  tupleIsAlive = true;
2449  break;
2451 
2452  /*
2453  * As with INSERT_IN_PROGRESS case, this is unexpected
2454  * unless it's our own deletion or a system catalog; but
2455  * in anyvisible mode, this tuple is visible.
2456  */
2457  if (anyvisible)
2458  {
2459  indexIt = true;
2460  tupleIsAlive = false;
2461  break;
2462  }
2463 
2464  xwait = HeapTupleHeaderGetUpdateXid(heapTuple->t_data);
2466  {
2467  if (!is_system_catalog)
2468  elog(WARNING, "concurrent delete in progress within table \"%s\"",
2469  RelationGetRelationName(heapRelation));
2470 
2471  /*
2472  * If we are performing uniqueness checks, assuming
2473  * the tuple is dead could lead to missing a
2474  * uniqueness violation. In that case we wait for the
2475  * deleting transaction to finish and check again.
2476  *
2477  * Also, if it's a HOT-updated tuple, we should not
2478  * index it but rather the live tuple at the end of
2479  * the HOT-chain. However, the deleting transaction
2480  * could abort, possibly leaving this tuple as live
2481  * after all, in which case it has to be indexed. The
2482  * only way to know what to do is to wait for the
2483  * deleting transaction to finish and check again.
2484  */
2485  if (checking_uniqueness ||
2486  HeapTupleIsHotUpdated(heapTuple))
2487  {
2488  /*
2489  * Must drop the lock on the buffer before we wait
2490  */
2492  XactLockTableWait(xwait, heapRelation,
2493  &heapTuple->t_self,
2496  goto recheck;
2497  }
2498 
2499  /*
2500  * Otherwise index it but don't check for uniqueness,
2501  * the same as a RECENTLY_DEAD tuple.
2502  */
2503  indexIt = true;
2504  }
2505  else if (HeapTupleIsHotUpdated(heapTuple))
2506  {
2507  /*
2508  * It's a HOT-updated tuple deleted by our own xact.
2509  * We can assume the deletion will commit (else the
2510  * index contents don't matter), so treat the same as
2511  * RECENTLY_DEAD HOT-updated tuples.
2512  */
2513  indexIt = false;
2514  /* mark the index as unsafe for old snapshots */
2515  indexInfo->ii_BrokenHotChain = true;
2516  }
2517  else
2518  {
2519  /*
2520  * It's a regular tuple deleted by our own xact. Index
2521  * it but don't check for uniqueness, the same as a
2522  * RECENTLY_DEAD tuple.
2523  */
2524  indexIt = true;
2525  }
2526  /* In any case, exclude the tuple from unique-checking */
2527  tupleIsAlive = false;
2528  break;
2529  default:
2530  elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
2531  indexIt = tupleIsAlive = false; /* keep compiler quiet */
2532  break;
2533  }
2534 
2536 
2537  if (!indexIt)
2538  continue;
2539  }
2540  else
2541  {
2542  /* heap_getnext did the time qual check */
2543  tupleIsAlive = true;
2544  }
2545 
2546  reltuples += 1;
2547 
2549 
2550  /* Set up for predicate or expression evaluation */
2551  ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
2552 
2553  /*
2554  * In a partial index, discard tuples that don't satisfy the
2555  * predicate.
2556  */
2557  if (predicate != NULL)
2558  {
2559  if (!ExecQual(predicate, econtext))
2560  continue;
2561  }
2562 
2563  /*
2564  * For the current heap tuple, extract all the attributes we use in
2565  * this index, and note which are null. This also performs evaluation
2566  * of any expressions needed.
2567  */
2568  FormIndexDatum(indexInfo,
2569  slot,
2570  estate,
2571  values,
2572  isnull);
2573 
2574  /*
2575  * You'd think we should go ahead and build the index tuple here, but
2576  * some index AMs want to do further processing on the data first. So
2577  * pass the values[] and isnull[] arrays, instead.
2578  */
2579 
2580  if (HeapTupleIsHeapOnly(heapTuple))
2581  {
2582  /*
2583  * For a heap-only tuple, pretend its TID is that of the root. See
2584  * src/backend/access/heap/README.HOT for discussion.
2585  */
2586  HeapTupleData rootTuple;
2587  OffsetNumber offnum;
2588 
2589  rootTuple = *heapTuple;
2590  offnum = ItemPointerGetOffsetNumber(&heapTuple->t_self);
2591 
2592  if (!OffsetNumberIsValid(root_offsets[offnum - 1]))
2593  elog(ERROR, "failed to find parent tuple for heap-only tuple at (%u,%u) in table \"%s\"",
2594  ItemPointerGetBlockNumber(&heapTuple->t_self),
2595  offnum, RelationGetRelationName(heapRelation));
2596 
2598  root_offsets[offnum - 1]);
2599 
2600  /* Call the AM's callback routine to process the tuple */
2601  callback(indexRelation, &rootTuple, values, isnull, tupleIsAlive,
2602  callback_state);
2603  }
2604  else
2605  {
2606  /* Call the AM's callback routine to process the tuple */
2607  callback(indexRelation, heapTuple, values, isnull, tupleIsAlive,
2608  callback_state);
2609  }
2610  }
2611 
2612  heap_endscan(scan);
2613 
2614  /* we can now forget our snapshot, if set */
2615  if (IsBootstrapProcessingMode() || indexInfo->ii_Concurrent)
2616  UnregisterSnapshot(snapshot);
2617 
2619 
2620  FreeExecutorState(estate);
2621 
2622  /* These may have been pointing to the now-gone estate */
2623  indexInfo->ii_ExpressionsState = NIL;
2624  indexInfo->ii_PredicateState = NULL;
2625 
2626  return reltuples;
2627 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:359
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:1769
#define NIL
Definition: pg_list.h:69
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
BlockNumber rs_cblock
Definition: relscan.h:69
List * ii_Predicate
Definition: execnodes.h:138
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1578
bool IsSystemRelation(Relation relation)
Definition: catalog.c:63
uint32 TransactionId
Definition: c.h:397
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
#define RelationGetDescr(relation)
Definition: rel.h:428
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:773
ExprState * ii_PredicateState
Definition: execnodes.h:139
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:203
#define MaxHeapTuplesPerPage
Definition: htup_details.h:575
#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:135
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:347
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:304
#define OidIsValid(objectId)
Definition: c.h:538
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
void FreeExecutorState(EState *estate)
Definition: execUtils.c:178
#define HeapTupleIsHotUpdated(tuple)
Definition: htup_details.h:677
#define GetPerTupleExprContext(estate)
Definition: executor.h:457
List * ii_ExpressionsState
Definition: execnodes.h:137
#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:216
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:436
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:465
static TransactionId OldestXmin
Definition: vacuumlazy.c:138
bool ii_BrokenHotChain
Definition: execnodes.h:149
void heap_setscanlimits(HeapScanDesc scan, BlockNumber startBlk, BlockNumber numBlks)
Definition: heapam.c:325
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:199
#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:372
#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:1794
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1314
HeapScanDesc heap_beginscan_strat(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, bool allow_strat, bool allow_sync)
Definition: heapam.c:1409
Buffer rs_cbuf
Definition: relscan.h:70
bool ii_Unique
Definition: execnodes.h:146
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
Definition: lmgr.c:554
#define NULL
Definition: c.h:229
#define HeapTupleIsHeapOnly(tuple)
Definition: htup_details.h:686
#define Assert(condition)
Definition: c.h:675
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
#define INDEX_MAX_KEYS
#define InvalidBlockNumber
Definition: block.h:33
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:197
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
bool ii_Concurrent
Definition: execnodes.h:148
#define ItemPointerSetOffsetNumber(pointer, offsetNumber)
Definition: itemptr.h:126
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
Oid * ii_ExclusionOps
Definition: execnodes.h:140
#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
Pointer Page
Definition: bufpage.h:74
double IndexBuildHeapScan ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
bool  allow_sync,
IndexBuildCallback  callback,
void *  callback_state 
)

Definition at line 2173 of file index.c.

References IndexBuildHeapRangeScan(), and InvalidBlockNumber.

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

2179 {
2180  return IndexBuildHeapRangeScan(heapRelation, indexRelation,
2181  indexInfo, allow_sync,
2182  false,
2183  0, InvalidBlockNumber,
2184  callback, callback_state);
2185 }
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
#define InvalidBlockNumber
Definition: block.h:33
double IndexBuildHeapRangeScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, bool anyvisible, BlockNumber start_blockno, BlockNumber numblocks, IndexBuildCallback callback, void *callback_state)
Definition: index.c:2198
Oid IndexGetRelation ( Oid  indexId,
bool  missing_ok 
)

Definition at line 3279 of file index.c.

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

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

3280 {
3281  HeapTuple tuple;
3283  Oid result;
3284 
3285  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
3286  if (!HeapTupleIsValid(tuple))
3287  {
3288  if (missing_ok)
3289  return InvalidOid;
3290  elog(ERROR, "cache lookup failed for index %u", indexId);
3291  }
3292  index = (Form_pg_index) GETSTRUCT(tuple);
3293  Assert(index->indexrelid == indexId);
3294 
3295  result = index->indrelid;
3296  ReleaseSysCache(tuple);
3297  return result;
3298 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1633
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
Definition: type.h:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:675
#define elog
Definition: elog.h:219
void reindex_index ( Oid  indexId,
bool  skip_constraint_checks,
char  relpersistence,
int  options 
)

Definition at line 3304 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, NULL, ObjectIdGetDatum, PG_CATCH, PG_END_TRY, PG_RE_THROW, pg_rusage_init(), pg_rusage_show(), PG_TRY, REINDEXOPT_VERBOSE, RELATION_IS_OTHER_TEMP, RelationSetNewRelfilenode(), ResetReindexProcessing(), RowExclusiveLock, SearchSysCacheCopy1, SetReindexProcessing(), ShareLock, HeapTupleData::t_self, and TransferPredicateLocksToHeapRelation().

Referenced by reindex_relation(), and ReindexIndex().

3306 {
3307  Relation iRel,
3308  heapRelation;
3309  Oid heapId;
3310  IndexInfo *indexInfo;
3311  volatile bool skipped_constraint = false;
3312  PGRUsage ru0;
3313 
3314  pg_rusage_init(&ru0);
3315 
3316  /*
3317  * Open and lock the parent heap relation. ShareLock is sufficient since
3318  * we only need to be sure no schema or data changes are going on.
3319  */
3320  heapId = IndexGetRelation(indexId, false);
3321  heapRelation = heap_open(heapId, ShareLock);
3322 
3323  /*
3324  * Open the target index relation and get an exclusive lock on it, to
3325  * ensure that no one else is touching this particular index.
3326  */
3327  iRel = index_open(indexId, AccessExclusiveLock);
3328 
3329  /*
3330  * Don't allow reindex on temp tables of other backends ... their local
3331  * buffer manager is not going to cope.
3332  */
3333  if (RELATION_IS_OTHER_TEMP(iRel))
3334  ereport(ERROR,
3335  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3336  errmsg("cannot reindex temporary tables of other sessions")));
3337 
3338  /*
3339  * Also check for active uses of the index in the current transaction; we
3340  * don't want to reindex underneath an open indexscan.
3341  */
3342  CheckTableNotInUse(iRel, "REINDEX INDEX");
3343 
3344  /*
3345  * All predicate locks on the index are about to be made invalid. Promote
3346  * them to relation locks on the heap.
3347  */
3349 
3350  PG_TRY();
3351  {
3352  /* Suppress use of the target index while rebuilding it */
3353  SetReindexProcessing(heapId, indexId);
3354 
3355  /* Fetch info needed for index_build */
3356  indexInfo = BuildIndexInfo(iRel);
3357 
3358  /* If requested, skip checking uniqueness/exclusion constraints */
3359  if (skip_constraint_checks)
3360  {
3361  if (indexInfo->ii_Unique || indexInfo->ii_ExclusionOps != NULL)
3362  skipped_constraint = true;
3363  indexInfo->ii_Unique = false;
3364  indexInfo->ii_ExclusionOps = NULL;
3365  indexInfo->ii_ExclusionProcs = NULL;
3366  indexInfo->ii_ExclusionStrats = NULL;
3367  }
3368 
3369  /* We'll build a new physical relation for the index */
3372 
3373  /* Initialize the index and rebuild */
3374  /* Note: we do not need to re-establish pkey setting */
3375  index_build(heapRelation, iRel, indexInfo, false, true);
3376  }
3377  PG_CATCH();
3378  {
3379  /* Make sure flag gets cleared on error exit */
3381  PG_RE_THROW();
3382  }
3383  PG_END_TRY();
3385 
3386  /*
3387  * If the index is marked invalid/not-ready/dead (ie, it's from a failed
3388  * CREATE INDEX CONCURRENTLY, or a DROP INDEX CONCURRENTLY failed midway),
3389  * and we didn't skip a uniqueness check, we can now mark it valid. This
3390  * allows REINDEX to be used to clean up in such cases.
3391  *
3392  * We can also reset indcheckxmin, because we have now done a
3393  * non-concurrent index build, *except* in the case where index_build
3394  * found some still-broken HOT chains. If it did, and we don't have to
3395  * change any of the other flags, we just leave indcheckxmin alone (note
3396  * that index_build won't have changed it, because this is a reindex).
3397  * This is okay and desirable because not updating the tuple leaves the
3398  * index's usability horizon (recorded as the tuple's xmin value) the same
3399  * as it was.
3400  *
3401  * But, if the index was invalid/not-ready/dead and there were broken HOT
3402  * chains, we had better force indcheckxmin true, because the normal
3403  * argument that the HOT chains couldn't conflict with the index is
3404  * suspect for an invalid index. (A conflict is definitely possible if
3405  * the index was dead. It probably shouldn't happen otherwise, but let's
3406  * be conservative.) In this case advancing the usability horizon is
3407  * appropriate.
3408  *
3409  * Another reason for avoiding unnecessary updates here is that while
3410  * reindexing pg_index itself, we must not try to update tuples in it.
3411  * pg_index's indexes should always have these flags in their clean state,
3412  * so that won't happen.
3413  *
3414  * If early pruning/vacuuming is enabled for the heap relation, the
3415  * usability horizon must be advanced to the current transaction on every
3416  * build or rebuild. pg_index is OK in this regard because catalog tables
3417  * are not subject to early cleanup.
3418  */
3419  if (!skipped_constraint)
3420  {
3421  Relation pg_index;
3422  HeapTuple indexTuple;
3423  Form_pg_index indexForm;
3424  bool index_bad;
3425  bool early_pruning_enabled = EarlyPruningEnabled(heapRelation);
3426 
3428 
3429  indexTuple = SearchSysCacheCopy1(INDEXRELID,
3430  ObjectIdGetDatum(indexId));
3431  if (!HeapTupleIsValid(indexTuple))
3432  elog(ERROR, "cache lookup failed for index %u", indexId);
3433  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
3434 
3435  index_bad = (!indexForm->indisvalid ||
3436  !indexForm->indisready ||
3437  !indexForm->indislive);
3438  if (index_bad ||
3439  (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain) ||
3440  early_pruning_enabled)
3441  {
3442  if (!indexInfo->ii_BrokenHotChain && !early_pruning_enabled)
3443  indexForm->indcheckxmin = false;
3444  else if (index_bad || early_pruning_enabled)
3445  indexForm->indcheckxmin = true;
3446  indexForm->indisvalid = true;
3447  indexForm->indisready = true;
3448  indexForm->indislive = true;
3449  CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
3450 
3451  /*
3452  * Invalidate the relcache for the table, so that after we commit
3453  * all sessions will refresh the table's index list. This ensures
3454  * that if anyone misses seeing the pg_index row during this
3455  * update, they'll refresh their list before attempting any update
3456  * on the table.
3457  */
3458  CacheInvalidateRelcache(heapRelation);
3459  }
3460 
3461  heap_close(pg_index, RowExclusiveLock);
3462  }
3463 
3464  /* Log what we did */
3466  ereport(INFO,
3467  (errmsg("index \"%s\" was reindexed",
3468  get_rel_name(indexId)),
3469  errdetail_internal("%s",
3470  pg_rusage_show(&ru0))));
3471 
3472  /* Close rels, but keep locks */
3473  index_close(iRel, NoLock);
3474  heap_close(heapRelation, NoLock);
3475 }
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3279
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3420
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static void SetReindexProcessing(Oid heapOid, Oid indexOid)
Definition: index.c:3698
#define IndexRelationId
Definition: pg_index.h:29
Oid * ii_ExclusionProcs
Definition: execnodes.h:141
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:1640
unsigned int Oid
Definition: postgres_ext.h:31
#define REINDEXOPT_VERBOSE
Definition: parsenodes.h:3208
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
static void ResetReindexProcessing(void)
Definition: index.c:3715
void pg_rusage_init(PGRUsage *ru0)
Definition: pg_rusage.c:27
#define EarlyPruningEnabled(rel)
Definition: snapmgr.h:46
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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
bool ii_BrokenHotChain
Definition: execnodes.h:149
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3010
#define ereport(elevel, rest)
Definition: elog.h:122
void TransferPredicateLocksToHeapRelation(Relation relation)
Definition: predicate.c:3088
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isprimary, bool isreindex)
Definition: index.c:2004
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define InvalidMultiXactId
Definition: multixact.h:23
bool ii_Unique
Definition: execnodes.h:146
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:533
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:176
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
#define AccessExclusiveLock
Definition: lockdefs.h:45
Oid * ii_ExclusionOps
Definition: execnodes.h:140
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:142
#define PG_TRY()
Definition: elog.h:284
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
#define PG_END_TRY()
Definition: elog.h:300
bool reindex_relation ( Oid  relid,
int  flags,
int  options 
)

Definition at line 3513 of file index.c.

References Assert, ClassOidIndexId, CommandCounterIncrement(), 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(), RelationGetRelid, RelationRelationId, RelationSetIndexList(), RELPERSISTENCE_PERMANENT, RELPERSISTENCE_UNLOGGED, ResetReindexPending(), result, SetReindexPending(), and ShareLock.

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

3514 {
3515  Relation rel;
3516  Oid toast_relid;
3517  List *indexIds;
3518  bool is_pg_class;
3519  bool result;
3520 
3521  /*
3522  * Open and lock the relation. ShareLock is sufficient since we only need
3523  * to prevent schema and data changes in it. The lock level used here
3524  * should match ReindexTable().
3525  */
3526  rel = heap_open(relid, ShareLock);
3527 
3528  toast_relid = rel->rd_rel->reltoastrelid;
3529 
3530  /*
3531  * Get the list of index OIDs for this relation. (We trust to the
3532  * relcache to get this with a sequential scan if ignoring system
3533  * indexes.)
3534  */
3535  indexIds = RelationGetIndexList(rel);
3536 
3537  /*
3538  * reindex_index will attempt to update the pg_class rows for the relation
3539  * and index. If we are processing pg_class itself, we want to make sure
3540  * that the updates do not try to insert index entries into indexes we
3541  * have not processed yet. (When we are trying to recover from corrupted
3542  * indexes, that could easily cause a crash.) We can accomplish this
3543  * because CatalogTupleInsert/CatalogTupleUpdate will use the relcache's
3544  * index list to know which indexes to update. We just force the index
3545  * list to be only the stuff we've processed.
3546  *
3547  * It is okay to not insert entries into the indexes we have not processed
3548  * yet because all of this is transaction-safe. If we fail partway
3549  * through, the updated rows are dead and it doesn't matter whether they
3550  * have index entries. Also, a new pg_class index will be created with a
3551  * correct entry for its own pg_class row because we do
3552  * RelationSetNewRelfilenode() before we do index_build().
3553  *
3554  * Note that we also clear pg_class's rd_oidindex until the loop is done,
3555  * so that that index can't be accessed either. This means we cannot
3556  * safely generate new relation OIDs while in the loop; shouldn't be a
3557  * problem.
3558  */
3559  is_pg_class = (RelationGetRelid(rel) == RelationRelationId);
3560 
3561  /* Ensure rd_indexattr is valid; see comments for RelationSetIndexList */
3562  if (is_pg_class)
3564 
3565  PG_TRY();
3566  {
3567  List *doneIndexes;
3568  ListCell *indexId;
3569  char persistence;
3570 
3571  if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
3572  {
3573  /* Suppress use of all the indexes until they are rebuilt */
3574  SetReindexPending(indexIds);
3575 
3576  /*
3577  * Make the new heap contents visible --- now things might be
3578  * inconsistent!
3579  */
3581  }
3582 
3583  /*
3584  * Compute persistence of indexes: same as that of owning rel, unless
3585  * caller specified otherwise.
3586  */
3588  persistence = RELPERSISTENCE_UNLOGGED;
3589  else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT)
3590  persistence = RELPERSISTENCE_PERMANENT;
3591  else
3592  persistence = rel->rd_rel->relpersistence;
3593 
3594  /* Reindex all the indexes. */
3595  doneIndexes = NIL;
3596  foreach(indexId, indexIds)
3597  {
3598  Oid indexOid = lfirst_oid(indexId);
3599 
3600  if (is_pg_class)
3601  RelationSetIndexList(rel, doneIndexes, InvalidOid);
3602 
3603  reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
3604  persistence, options);
3605 
3607 
3608  /* Index should no longer be in the pending list */
3609  Assert(!ReindexIsProcessingIndex(indexOid));
3610 
3611  if (is_pg_class)
3612  doneIndexes = lappend_oid(doneIndexes, indexOid);
3613  }
3614  }
3615  PG_CATCH();
3616  {
3617  /* Make sure list gets cleared on error exit */
3619  PG_RE_THROW();
3620  }
3621  PG_END_TRY();
3623 
3624  if (is_pg_class)
3625  RelationSetIndexList(rel, indexIds, ClassOidIndexId);
3626 
3627  /*
3628  * Close rel, but continue to hold the lock.
3629  */
3630  heap_close(rel, NoLock);
3631 
3632  result = (indexIds != NIL);
3633 
3634  /*
3635  * If the relation has a secondary toast rel, reindex that too while we
3636  * still hold the lock on the master table.
3637  */
3638  if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid))
3639  result |= reindex_relation(toast_relid, flags, options);
3640 
3641  return result;
3642 }
#define NIL
Definition: pg_list.h:69
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
static void SetReindexPending(List *indexes)
Definition: index.c:3729
#define RelationRelationId
Definition: pg_class.h:29
static void ResetReindexPending(void)
Definition: index.c:3753
return result
Definition: formatting.c:1633
#define heap_close(r, l)
Definition: heapam.h:97
#define REINDEX_REL_SUPPRESS_INDEX_USE
Definition: index.h:123
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:538
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
void RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
Definition: relcache.c:4600
#define NoLock
Definition: lockdefs.h:34
#define ClassOidIndexId
Definition: indexing.h:112
void CommandCounterIncrement(void)
Definition: xact.c:922
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_CATCH()
Definition: elog.h:293
#define REINDEX_REL_FORCE_INDEXES_UNLOGGED
Definition: index.h:125
#define Assert(condition)
Definition: c.h:675
#define REINDEX_REL_CHECK_CONSTRAINTS
Definition: index.h:124
#define PG_RE_THROW()
Definition: elog.h:314
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4349
void reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, int options)
Definition: index.c:3304
#define ShareLock
Definition: lockdefs.h:41
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:4851
#define REINDEX_REL_FORCE_INDEXES_PERMANENT
Definition: index.h:126
#define REINDEX_REL_PROCESS_TOAST
Definition: index.h:122
#define PG_TRY()
Definition: elog.h:284
bool ReindexIsProcessingIndex(Oid indexOid)
Definition: index.c:3685
bool reindex_relation(Oid relid, int flags, int options)
Definition: index.c:3513
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:416
#define PG_END_TRY()
Definition: elog.h:300
#define lfirst_oid(lc)
Definition: pg_list.h:108
bool ReindexIsProcessingHeap ( Oid  heapOid)

Definition at line 3664 of file index.c.

References currentlyReindexedHeap.

Referenced by index_update_stats().

3665 {
3666  return heapOid == currentlyReindexedHeap;
3667 }
static Oid currentlyReindexedHeap
Definition: index.c:3655
bool ReindexIsProcessingIndex ( Oid  indexOid)

Definition at line 3685 of file index.c.

References currentlyReindexedIndex, and list_member_oid().

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

3686 {
3687  return indexOid == currentlyReindexedIndex ||
3689 }
static List * pendingReindexedIndexes
Definition: index.c:3657
static Oid currentlyReindexedIndex
Definition: index.c:3656
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
void validate_index ( Oid  heapId,
Oid  indexId,
Snapshot  snapshot 
)

Definition at line 2803 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, NULL, 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().

2804 {
2805  Relation heapRelation,
2806  indexRelation;
2807  IndexInfo *indexInfo;
2808  IndexVacuumInfo ivinfo;
2809  v_i_state state;
2810  Oid save_userid;
2811  int save_sec_context;
2812  int save_nestlevel;
2813 
2814  /* Open and lock the parent heap relation */
2815  heapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
2816  /* And the target index relation */
2817  indexRelation = index_open(indexId, RowExclusiveLock);
2818 
2819  /*
2820  * Fetch info needed for index_insert. (You might think this should be
2821  * passed in from DefineIndex, but its copy is long gone due to having
2822  * been built in a previous transaction.)
2823  */
2824  indexInfo = BuildIndexInfo(indexRelation);
2825 
2826  /* mark build is concurrent just for consistency */
2827  indexInfo->ii_Concurrent = true;
2828 
2829  /*
2830  * Switch to the table owner's userid, so that any index functions are run
2831  * as that user. Also lock down security-restricted operations and
2832  * arrange to make GUC variable changes local to this command.
2833  */
2834  GetUserIdAndSecContext(&save_userid, &save_sec_context);
2835  SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
2836  save_sec_context | SECURITY_RESTRICTED_OPERATION);
2837  save_nestlevel = NewGUCNestLevel();
2838 
2839  /*
2840  * Scan the index and gather up all the TIDs into a tuplesort object.
2841  */
2842  ivinfo.index = indexRelation;
2843  ivinfo.analyze_only = false;
2844  ivinfo.estimated_count = true;
2845  ivinfo.message_level = DEBUG2;
2846  ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
2847  ivinfo.strategy = NULL;
2848 
2849  /*
2850  * Encode TIDs as int8 values for the sort, rather than directly sorting
2851  * item pointers. This can be significantly faster, primarily because TID
2852  * is a pass-by-reference type on all platforms, whereas int8 is
2853  * pass-by-value on most platforms.
2854  */
2856  InvalidOid, false,
2858  false);
2859  state.htups = state.itups = state.tups_inserted = 0;
2860 
2861  (void) index_bulk_delete(&ivinfo, NULL,
2862  validate_index_callback, (void *) &state);
2863 
2864  /* Execute the sort */
2866 
2867  /*
2868  * Now scan the heap and "merge" it with the index
2869  */
2870  validate_index_heapscan(heapRelation,
2871  indexRelation,
2872  indexInfo,
2873  snapshot,
2874  &state);
2875 
2876  /* Done with tuplesort object */
2877  tuplesort_end(state.tuplesort);
2878 
2879  elog(DEBUG2,
2880  "validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
2881  state.htups, state.itups, state.tups_inserted);
2882 
2883  /* Roll back any GUC changes executed by index functions */
2884  AtEOXact_GUC(false, save_nestlevel);
2885 
2886  /* Restore userid and security context */
2887  SetUserIdAndSecContext(save_userid, save_sec_context);
2888 
2889  /* Close rels, but keep locks */
2890  index_close(indexRelation, NoLock);
2891  heap_close(heapRelation, NoLock);
2892 }
#define Int8LessOperator
Definition: pg_operator.h:181
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1773
#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:84
#define heap_close(r, l)
Definition: heapam.h:97
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:1640
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
Tuplesortstate * tuplesort
Definition: index.c:82
#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:2955
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, bool randomAccess)
Definition: tuplesort.c:1038
#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:5079
IndexBulkDeleteResult * index_bulk_delete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
Definition: indexam.c:743
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#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
#define NULL
Definition: c.h:229
Definition: regguts.h:298
bool ii_Concurrent
Definition: execnodes.h:148
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
double itups
Definition: index.c:84
int NewGUCNestLevel(void)
Definition: guc.c:5065
#define elog
Definition: elog.h:219
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1167
static bool validate_index_callback(ItemPointer itemptr, void *opaque)
Definition: index.c:2938
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
double tups_inserted
Definition: index.c:84
bool estimated_count
Definition: genam.h:48