PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
index.c File Reference
#include "postgres.h"
#include <unistd.h>
#include "access/amapi.h"
#include "access/multixact.h"
#include "access/relscan.h"
#include "access/sysattr.h"
#include "access/transam.h"
#include "access/visibilitymap.h"
#include "access/xact.h"
#include "bootstrap/bootstrap.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_am.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_constraint_fn.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "catalog/storage.h"
#include "commands/tablecmds.h"
#include "commands/trigger.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "parser/parser.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/procarray.h"
#include "storage/smgr.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/pg_rusage.h"
#include "utils/syscache.h"
#include "utils/tuplesort.h"
#include "utils/snapmgr.h"
#include "utils/tqual.h"
Include dependency graph for index.c:

Go to the source code of this file.

Data Structures

struct  v_i_state
 

Functions

static bool relationHasPrimaryKey (Relation rel)
 
static TupleDesc ConstructTupleDescriptor (Relation heapRelation, IndexInfo *indexInfo, List *indexColNames, Oid accessMethodObjectId, Oid *collationObjectId, Oid *classObjectId)
 
static void InitializeAttributeOids (Relation indexRelation, int numatts, Oid indexoid)
 
static void AppendAttributeTuples (Relation indexRelation, int numatts)
 
static void UpdateIndexRelation (Oid indexoid, Oid heapoid, IndexInfo *indexInfo, Oid *collationOids, Oid *classOids, int16 *coloptions, bool primary, bool isexclusion, bool immediate, bool isvalid)
 
static void index_update_stats (Relation rel, bool hasindex, bool isprimary, double reltuples)
 
static void IndexCheckExclusion (Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo)
 
static int64 itemptr_encode (ItemPointer itemptr)
 
static void itemptr_decode (ItemPointer itemptr, int64 encoded)
 
static bool validate_index_callback (ItemPointer itemptr, void *opaque)
 
static void validate_index_heapscan (Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, Snapshot snapshot, v_i_state *state)
 
static bool ReindexIsCurrentlyProcessingIndex (Oid indexOid)
 
static void SetReindexProcessing (Oid heapOid, Oid indexOid)
 
static void ResetReindexProcessing (void)
 
static void SetReindexPending (List *indexes)
 
static void RemoveReindexPending (Oid indexOid)
 
static void ResetReindexPending (void)
 
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 numblocks, IndexBuildCallback callback, void *callback_state)
 
void validate_index (Oid heapId, Oid indexId, Snapshot snapshot)
 
void index_set_state_flags (Oid indexId, IndexStateFlagsAction action)
 
Oid IndexGetRelation (Oid indexId, bool missing_ok)
 
void reindex_index (Oid indexId, bool skip_constraint_checks, char persistence, int options)
 
bool reindex_relation (Oid relid, int flags, int options)
 
bool ReindexIsProcessingHeap (Oid heapOid)
 
bool ReindexIsProcessingIndex (Oid indexOid)
 

Variables

Oid binary_upgrade_next_index_pg_class_oid = InvalidOid
 
static Oid currentlyReindexedHeap = InvalidOid
 
static Oid currentlyReindexedIndex = InvalidOid
 
static ListpendingReindexedIndexes = NIL
 

Function Documentation

static void AppendAttributeTuples ( Relation  indexRelation,
int  numatts 
)
static

Definition at line 507 of file index.c.

References Assert, AttributeRelationId, CatalogCloseIndexes(), CatalogOpenIndexes(), heap_close, heap_open(), i, InsertPgAttributeTuple(), RelationGetDescr, RowExclusiveLock, and TupleDescAttr.

Referenced by index_create().

508 {
509  Relation pg_attribute;
510  CatalogIndexState indstate;
511  TupleDesc indexTupDesc;
512  int i;
513 
514  /*
515  * open the attribute relation and its indexes
516  */
518 
519  indstate = CatalogOpenIndexes(pg_attribute);
520 
521  /*
522  * insert data from new index's tupdesc into pg_attribute
523  */
524  indexTupDesc = RelationGetDescr(indexRelation);
525 
526  for (i = 0; i < numatts; i++)
527  {
528  Form_pg_attribute attr = TupleDescAttr(indexTupDesc, i);
529 
530  /*
531  * There used to be very grotty code here to set these fields, but I
532  * think it's unnecessary. They should be set already.
533  */
534  Assert(attr->attnum == i + 1);
535  Assert(attr->attcacheoff == -1);
536 
537  InsertPgAttributeTuple(pg_attribute, attr, indstate);
538  }
539 
540  CatalogCloseIndexes(indstate);
541 
542  heap_close(pg_attribute, RowExclusiveLock);
543 }
#define RelationGetDescr(relation)
Definition: rel.h:428
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#define AttributeRelationId
Definition: pg_attribute.h:33
#define heap_close(r, l)
Definition: heapam.h:97
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Assert(condition)
Definition: c.h:664
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:40
void InsertPgAttributeTuple(Relation pg_attribute_rel, Form_pg_attribute new_attribute, CatalogIndexState indstate)
Definition: heap.c:600
int i
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:58
IndexInfo* BuildIndexInfo ( Relation  index)

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

1643 {
1644  IndexInfo *ii = makeNode(IndexInfo);
1645  Form_pg_index indexStruct = index->rd_index;
1646  int i;
1647  int numKeys;
1648 
1649  /* check the number of keys, and copy attr numbers into the IndexInfo */
1650  numKeys = indexStruct->indnatts;
1651  if (numKeys < 1 || numKeys > INDEX_MAX_KEYS)
1652  elog(ERROR, "invalid indnatts %d for index %u",
1653  numKeys, RelationGetRelid(index));
1654  ii->ii_NumIndexAttrs = numKeys;
1655  for (i = 0; i < numKeys; i++)
1656  ii->ii_KeyAttrNumbers[i] = indexStruct->indkey.values[i];
1657 
1658  /* fetch any expressions needed for expressional indexes */
1660  ii->ii_ExpressionsState = NIL;
1661 
1662  /* fetch index predicate if any */
1664  ii->ii_PredicateState = NULL;
1665 
1666  /* fetch exclusion constraint info if any */
1667  if (indexStruct->indisexclusion)
1668  {
1670  &ii->ii_ExclusionOps,
1671  &ii->ii_ExclusionProcs,
1672  &ii->ii_ExclusionStrats);
1673  }
1674  else
1675  {
1676  ii->ii_ExclusionOps = NULL;
1677  ii->ii_ExclusionProcs = NULL;
1678  ii->ii_ExclusionStrats = NULL;
1679  }
1680 
1681  /* other info */
1682  ii->ii_Unique = indexStruct->indisunique;
1683  ii->ii_ReadyForInserts = IndexIsReady(indexStruct);
1684  /* assume not doing speculative insertion for now */
1685  ii->ii_UniqueOps = NULL;
1686  ii->ii_UniqueProcs = NULL;
1687  ii->ii_UniqueStrats = NULL;
1688 
1689  /* initialize index-build state to default */
1690  ii->ii_Concurrent = false;
1691  ii->ii_BrokenHotChain = false;
1692 
1693  /* set up for possible use by index AM */
1694  ii->ii_AmCache = NULL;
1696 
1697  return ii;
1698 }
#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:5066
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:4776
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:4713
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
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 1713 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().

1714 {
1715  int ncols = index->rd_rel->relnatts;
1716  int i;
1717 
1718  /*
1719  * fetch info for checking unique indexes
1720  */
1721  Assert(ii->ii_Unique);
1722 
1723  if (index->rd_rel->relam != BTREE_AM_OID)
1724  elog(ERROR, "unexpected non-btree speculative unique index");
1725 
1726  ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * ncols);
1727  ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * ncols);
1728  ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * ncols);
1729 
1730  /*
1731  * We have to look up the operator's strategy number. This provides a
1732  * cross-check that the operator does match the index.
1733  */
1734  /* We need the func OIDs and strategy numbers too */
1735  for (i = 0; i < ncols; i++)
1736  {
1738  ii->ii_UniqueOps[i] =
1739  get_opfamily_member(index->rd_opfamily[i],
1740  index->rd_opcintype[i],
1741  index->rd_opcintype[i],
1742  ii->ii_UniqueStrats[i]);
1743  if (!OidIsValid(ii->ii_UniqueOps[i]))
1744  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
1745  ii->ii_UniqueStrats[i], index->rd_opcintype[i],
1746  index->rd_opcintype[i], index->rd_opfamily[i]);
1747  ii->ii_UniqueProcs[i] = get_opcode(ii->ii_UniqueOps[i]);
1748  }
1749 }
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:532
Oid * ii_UniqueOps
Definition: execnodes.h:143
unsigned short uint16
Definition: c.h:257
#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:664
void * palloc(Size size)
Definition: mcxt.c:848
int i
#define elog
Definition: elog.h:219
Oid * rd_opcintype
Definition: rel.h:183
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static TupleDesc ConstructTupleDescriptor ( Relation  heapRelation,
IndexInfo indexInfo,
List indexColNames,
Oid  accessMethodObjectId,
Oid collationObjectId,
Oid classObjectId 
)
static

Definition at line 274 of file index.c.

References IndexAmRoutine::amkeytype, ANYARRAYOID, ANYELEMENTOID, ATTRIBUTE_FIXED_PART_SIZE, AttrNumberGetAttrOffset, CheckAttributeType(), CLAOID, CreateTemplateTupleDesc(), elog, ERROR, exprType(), exprTypmod(), get_base_element_type(), GetIndexAmRoutineByAmId(), GETSTRUCT, HeapTupleIsValid, i, IndexInfo::ii_Expressions, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, InvalidOid, lfirst, list_head(), lnext, MemSet, NameStr, namestrcpy(), NIL, ObjectIdGetDatum, OidIsValid, pfree(), RelationData::rd_rel, RelationGetDescr, RelationGetForm, ReleaseSysCache(), SearchSysCache1, SystemAttributeDefinition(), TupleDescAttr, and TYPEOID.

Referenced by index_create().

280 {
281  int numatts = indexInfo->ii_NumIndexAttrs;
282  ListCell *colnames_item = list_head(indexColNames);
283  ListCell *indexpr_item = list_head(indexInfo->ii_Expressions);
284  IndexAmRoutine *amroutine;
285  TupleDesc heapTupDesc;
286  TupleDesc indexTupDesc;
287  int natts; /* #atts in heap rel --- for error checks */
288  int i;
289 
290  /* We need access to the index AM's API struct */
291  amroutine = GetIndexAmRoutineByAmId(accessMethodObjectId, false);
292 
293  /* ... and to the table's tuple descriptor */
294  heapTupDesc = RelationGetDescr(heapRelation);
295  natts = RelationGetForm(heapRelation)->relnatts;
296 
297  /*
298  * allocate the new tuple descriptor
299  */
300  indexTupDesc = CreateTemplateTupleDesc(numatts, false);
301 
302  /*
303  * For simple index columns, we copy the pg_attribute row from the parent
304  * relation and modify it as necessary. For expressions we have to cons
305  * up a pg_attribute row the hard way.
306  */
307  for (i = 0; i < numatts; i++)
308  {
309  AttrNumber atnum = indexInfo->ii_KeyAttrNumbers[i];
310  Form_pg_attribute to = TupleDescAttr(indexTupDesc, i);
311  HeapTuple tuple;
312  Form_pg_type typeTup;
313  Form_pg_opclass opclassTup;
314  Oid keyType;
315 
316  if (atnum != 0)
317  {
318  /* Simple index column */
319  Form_pg_attribute from;
320 
321  if (atnum < 0)
322  {
323  /*
324  * here we are indexing on a system attribute (-1...-n)
325  */
326  from = SystemAttributeDefinition(atnum,
327  heapRelation->rd_rel->relhasoids);
328  }
329  else
330  {
331  /*
332  * here we are indexing on a normal attribute (1...n)
333  */
334  if (atnum > natts) /* safety check */
335  elog(ERROR, "invalid column number %d", atnum);
336  from = TupleDescAttr(heapTupDesc,
337  AttrNumberGetAttrOffset(atnum));
338  }
339 
340  /*
341  * now that we've determined the "from", let's copy the tuple desc
342  * data...
343  */
344  memcpy(to, from, ATTRIBUTE_FIXED_PART_SIZE);
345 
346  /*
347  * Fix the stuff that should not be the same as the underlying
348  * attr
349  */
350  to->attnum = i + 1;
351 
352  to->attstattarget = -1;
353  to->attcacheoff = -1;
354  to->attnotnull = false;
355  to->atthasdef = false;
356  to->attidentity = '\0';
357  to->attislocal = true;
358  to->attinhcount = 0;
359  to->attcollation = collationObjectId[i];
360  }
361  else
362  {
363  /* Expressional index */
364  Node *indexkey;
365 
367 
368  if (indexpr_item == NULL) /* shouldn't happen */
369  elog(ERROR, "too few entries in indexprs list");
370  indexkey = (Node *) lfirst(indexpr_item);
371  indexpr_item = lnext(indexpr_item);
372 
373  /*
374  * Lookup the expression type in pg_type for the type length etc.
375  */
376  keyType = exprType(indexkey);
377  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
378  if (!HeapTupleIsValid(tuple))
379  elog(ERROR, "cache lookup failed for type %u", keyType);
380  typeTup = (Form_pg_type) GETSTRUCT(tuple);
381 
382  /*
383  * Assign some of the attributes values. Leave the rest as 0.
384  */
385  to->attnum = i + 1;
386  to->atttypid = keyType;
387  to->attlen = typeTup->typlen;
388  to->attbyval = typeTup->typbyval;
389  to->attstorage = typeTup->typstorage;
390  to->attalign = typeTup->typalign;
391  to->attstattarget = -1;
392  to->attcacheoff = -1;
393  to->atttypmod = exprTypmod(indexkey);
394  to->attislocal = true;
395  to->attcollation = collationObjectId[i];
396 
397  ReleaseSysCache(tuple);
398 
399  /*
400  * Make sure the expression yields a type that's safe to store in
401  * an index. We need this defense because we have index opclasses
402  * for pseudo-types such as "record", and the actually stored type
403  * had better be safe; eg, a named composite type is okay, an
404  * anonymous record type is not. The test is the same as for
405  * whether a table column is of a safe type (which is why we
406  * needn't check for the non-expression case).
407  */
408  CheckAttributeType(NameStr(to->attname),
409  to->atttypid, to->attcollation,
410  NIL, false);
411  }
412 
413  /*
414  * We do not yet have the correct relation OID for the index, so just
415  * set it invalid for now. InitializeAttributeOids() will fix it
416  * later.
417  */
418  to->attrelid = InvalidOid;
419 
420  /*
421  * Set the attribute name as specified by caller.
422  */
423  if (colnames_item == NULL) /* shouldn't happen */
424  elog(ERROR, "too few entries in colnames list");
425  namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
426  colnames_item = lnext(colnames_item);
427 
428  /*
429  * Check the opclass and index AM to see if either provides a keytype
430  * (overriding the attribute type). Opclass takes precedence.
431  */
432  tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(classObjectId[i]));
433  if (!HeapTupleIsValid(tuple))
434  elog(ERROR, "cache lookup failed for opclass %u",
435  classObjectId[i]);
436  opclassTup = (Form_pg_opclass) GETSTRUCT(tuple);
437  if (OidIsValid(opclassTup->opckeytype))
438  keyType = opclassTup->opckeytype;
439  else
440  keyType = amroutine->amkeytype;
441 
442  /*
443  * If keytype is specified as ANYELEMENT, and opcintype is ANYARRAY,
444  * then the attribute type must be an array (else it'd not have
445  * matched this opclass); use its element type.
446  */
447  if (keyType == ANYELEMENTOID && opclassTup->opcintype == ANYARRAYOID)
448  {
449  keyType = get_base_element_type(to->atttypid);
450  if (!OidIsValid(keyType))
451  elog(ERROR, "could not get element type of array type %u",
452  to->atttypid);
453  }
454 
455  ReleaseSysCache(tuple);
456 
457  /*
458  * If a key type different from the heap value is specified, update
459  * the type-related fields in the index tupdesc.
460  */
461  if (OidIsValid(keyType) && keyType != to->atttypid)
462  {
463  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
464  if (!HeapTupleIsValid(tuple))
465  elog(ERROR, "cache lookup failed for type %u", keyType);
466  typeTup = (Form_pg_type) GETSTRUCT(tuple);
467 
468  to->atttypid = keyType;
469  to->atttypmod = -1;
470  to->attlen = typeTup->typlen;
471  to->attbyval = typeTup->typbyval;
472  to->attalign = typeTup->typalign;
473  to->attstorage = typeTup->typstorage;
474 
475  ReleaseSysCache(tuple);
476  }
477  }
478 
479  pfree(amroutine);
480 
481  return indexTupDesc;
482 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationGetDescr(relation)
Definition: rel.h:428
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#define RelationGetForm(relation)
Definition: rel.h:410
#define ANYELEMENTOID
Definition: pg_type.h:702
Definition: nodes.h:509
#define MemSet(start, val, len)
Definition: c.h:846
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:216
Oid amkeytype
Definition: amapi.h:195
#define OidIsValid(objectId)
Definition: c.h:532
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:159
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition: amapi.c:56
#define AttrNumberGetAttrOffset(attNum)
Definition: attnum.h:51
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:179
#define lnext(lc)
Definition: pg_list.h:105
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, bool allow_system_table_mods)
Definition: heap.c:490
#define ANYARRAYOID
Definition: pg_type.h:688
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
int ii_NumIndexAttrs
Definition: execnodes.h:134
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:200
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
List * ii_Expressions
Definition: execnodes.h:136
#define lfirst(lc)
Definition: pg_list.h:106
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:135
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2557
int i
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
int16 AttrNumber
Definition: attnum.h:21
void FormIndexDatum ( IndexInfo indexInfo,
TupleTableSlot slot,
EState estate,
Datum values,
bool isnull 
)

Definition at line 1771 of file index.c.

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

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

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

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

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

198 {
199  List *cmds;
200  int i;
201 
202  /*
203  * If ALTER TABLE, check that there isn't already a PRIMARY KEY. In CREATE
204  * TABLE, we have faith that the parser rejected multiple pkey clauses;
205  * and CREATE INDEX doesn't have a way to say PRIMARY KEY, so it's no
206  * problem either.
207  */
208  if (is_alter_table &&
209  relationHasPrimaryKey(heapRel))
210  {
211  ereport(ERROR,
212  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
213  errmsg("multiple primary keys for table \"%s\" are not allowed",
214  RelationGetRelationName(heapRel))));
215  }
216 
217  /*
218  * Check that all of the attributes in a primary key are marked as not
219  * null, otherwise attempt to ALTER TABLE .. SET NOT NULL
220  */
221  cmds = NIL;
222  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
223  {
224  AttrNumber attnum = indexInfo->ii_KeyAttrNumbers[i];
225  HeapTuple atttuple;
226  Form_pg_attribute attform;
227 
228  if (attnum == 0)
229  ereport(ERROR,
230  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
231  errmsg("primary keys cannot be expressions")));
232 
233  /* System attributes are never null, so no need to check */
234  if (attnum < 0)
235  continue;
236 
237  atttuple = SearchSysCache2(ATTNUM,
239  Int16GetDatum(attnum));
240  if (!HeapTupleIsValid(atttuple))
241  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
242  attnum, RelationGetRelid(heapRel));
243  attform = (Form_pg_attribute) GETSTRUCT(atttuple);
244 
245  if (!attform->attnotnull)
246  {
247  /* Add a subcommand to make this one NOT NULL */
249 
250  cmd->subtype = AT_SetNotNull;
251  cmd->name = pstrdup(NameStr(attform->attname));
252  cmds = lappend(cmds, cmd);
253  }
254 
255  ReleaseSysCache(atttuple);
256  }
257 
258  /*
259  * XXX: possible future improvement: when being called from ALTER TABLE,
260  * it would be more efficient to merge this with the outer ALTER TABLE, so
261  * as to avoid two scans. But that seems to complicate DefineIndex's API
262  * unduly.
263  */
264  if (cmds)
265  AlterTableInternal(RelationGetRelid(heapRel), cmds, true);
266 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
char * pstrdup(const char *in)
Definition: mcxt.c:1076
#define Int16GetDatum(X)
Definition: postgres.h:457
int errcode(int sqlerrcode)
Definition: elog.c:575
AlterTableType subtype
Definition: parsenodes.h:1778
#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:3165
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:493
#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: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 at line 1150 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, 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().

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

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

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

3203 {
3204  Relation pg_index;
3205  HeapTuple indexTuple;
3206  Form_pg_index indexForm;
3207 
3208  /* Assert that current xact hasn't done any transactional updates */
3210 
3211  /* Open pg_index and fetch a writable copy of the index's tuple */
3213 
3214  indexTuple = SearchSysCacheCopy1(INDEXRELID,
3215  ObjectIdGetDatum(indexId));
3216  if (!HeapTupleIsValid(indexTuple))
3217  elog(ERROR, "cache lookup failed for index %u", indexId);
3218  indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
3219 
3220  /* Perform the requested state change on the copy */
3221  switch (action)
3222  {
3224  /* Set indisready during a CREATE INDEX CONCURRENTLY sequence */
3225  Assert(indexForm->indislive);
3226  Assert(!indexForm->indisready);
3227  Assert(!indexForm->indisvalid);
3228  indexForm->indisready = true;
3229  break;
3231  /* Set indisvalid during a CREATE INDEX CONCURRENTLY sequence */
3232  Assert(indexForm->indislive);
3233  Assert(indexForm->indisready);
3234  Assert(!indexForm->indisvalid);
3235  indexForm->indisvalid = true;
3236  break;
3238 
3239  /*
3240  * Clear indisvalid during a DROP INDEX CONCURRENTLY sequence
3241  *
3242  * If indisready == true we leave it set so the index still gets
3243  * maintained by active transactions. We only need to ensure that
3244  * indisvalid is false. (We don't assert that either is initially
3245  * true, though, since we want to be able to retry a DROP INDEX
3246  * CONCURRENTLY that failed partway through.)
3247  *
3248  * Note: the CLUSTER logic assumes that indisclustered cannot be
3249  * set on any invalid index, so clear that flag too.
3250  */
3251  indexForm->indisvalid = false;
3252  indexForm->indisclustered = false;
3253  break;
3254  case INDEX_DROP_SET_DEAD:
3255 
3256  /*
3257  * Clear indisready/indislive during DROP INDEX CONCURRENTLY
3258  *
3259  * We clear both indisready and indislive, because we not only
3260  * want to stop updates, we want to prevent sessions from touching
3261  * the index at all.
3262  */
3263  Assert(!indexForm->indisvalid);
3264  indexForm->indisready = false;
3265  indexForm->indislive = false;
3266  break;
3267  }
3268 
3269  /* ... and write it back in-place */
3270  heap_inplace_update(pg_index, indexTuple);
3271 
3272  heap_close(pg_index, RowExclusiveLock);
3273 }
#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:405
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:664
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:168
void heap_inplace_update(Relation relation, HeapTuple tuple)
Definition: heapam.c:6246
#define elog
Definition: elog.h:219
static void index_update_stats ( Relation  rel,
bool  hasindex,
bool  isprimary,
double  reltuples 
)
static

Definition at line 1849 of file index.c.

References BTEqualStrategyNumber, CacheInvalidateRelcacheByTuple(), elog, ERROR, ForwardScanDirection, GETSTRUCT, heap_beginscan_catalog(), heap_close, heap_copytuple(), heap_endscan(), heap_freetuple(), heap_getnext(), heap_inplace_update(), heap_open(), HeapTupleIsValid, IsBootstrapProcessingMode, ObjectIdAttributeNumber, ObjectIdGetDatum, ReindexIsProcessingHeap(), RelationGetNumberOfBlocks, RelationGetRelid, RelationRelationId, RELKIND_INDEX, RELOID, RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy1, and visibilitymap_count().

Referenced by index_build(), index_constraint_create(), and index_create().

1853 {
1854  Oid relid = RelationGetRelid(rel);
1855  Relation pg_class;
1856  HeapTuple tuple;
1857  Form_pg_class rd_rel;
1858  bool dirty;
1859 
1860  /*
1861  * We always update the pg_class row using a non-transactional,
1862  * overwrite-in-place update. There are several reasons for this:
1863  *
1864  * 1. In bootstrap mode, we have no choice --- UPDATE wouldn't work.
1865  *
1866  * 2. We could be reindexing pg_class itself, in which case we can't move
1867  * its pg_class row because CatalogTupleInsert/CatalogTupleUpdate might
1868  * not know about all the indexes yet (see reindex_relation).
1869  *
1870  * 3. Because we execute CREATE INDEX with just share lock on the parent
1871  * rel (to allow concurrent index creations), an ordinary update could
1872  * suffer a tuple-concurrently-updated failure against another CREATE
1873  * INDEX committing at about the same time. We can avoid that by having
1874  * them both do nontransactional updates (we assume they will both be
1875  * trying to change the pg_class row to the same thing, so it doesn't
1876  * matter which goes first).
1877  *
1878  * It is safe to use a non-transactional update even though our
1879  * transaction could still fail before committing. Setting relhasindex
1880  * true is safe even if there are no indexes (VACUUM will eventually fix
1881  * it), likewise for relhaspkey. And of course the new relpages and
1882  * reltuples counts are correct regardless. However, we don't want to
1883  * change relpages (or relallvisible) if the caller isn't providing an
1884  * updated reltuples count, because that would bollix the
1885  * reltuples/relpages ratio which is what's really important.
1886  */
1887 
1889 
1890  /*
1891  * Make a copy of the tuple to update. Normally we use the syscache, but
1892  * we can't rely on that during bootstrap or while reindexing pg_class
1893  * itself.
1894  */
1895  if (IsBootstrapProcessingMode() ||
1897  {
1898  /* don't assume syscache will work */
1899  HeapScanDesc pg_class_scan;
1900  ScanKeyData key[1];
1901 
1902  ScanKeyInit(&key[0],
1904  BTEqualStrategyNumber, F_OIDEQ,
1905  ObjectIdGetDatum(relid));
1906 
1907  pg_class_scan = heap_beginscan_catalog(pg_class, 1, key);
1908  tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
1909  tuple = heap_copytuple(tuple);
1910  heap_endscan(pg_class_scan);
1911  }
1912  else
1913  {
1914  /* normal case, use syscache */
1915  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
1916  }
1917 
1918  if (!HeapTupleIsValid(tuple))
1919  elog(ERROR, "could not find tuple for relation %u", relid);
1920  rd_rel = (Form_pg_class) GETSTRUCT(tuple);
1921 
1922  /* Apply required updates, if any, to copied tuple */
1923 
1924  dirty = false;
1925  if (rd_rel->relhasindex != hasindex)
1926  {
1927  rd_rel->relhasindex = hasindex;
1928  dirty = true;
1929  }
1930  if (isprimary)
1931  {
1932  if (!rd_rel->relhaspkey)
1933  {
1934  rd_rel->relhaspkey = true;
1935  dirty = true;
1936  }
1937  }
1938 
1939  if (reltuples >= 0)
1940  {
1941  BlockNumber relpages = RelationGetNumberOfBlocks(rel);
1942  BlockNumber relallvisible;
1943 
1944  if (rd_rel->relkind != RELKIND_INDEX)
1945  visibilitymap_count(rel, &relallvisible, NULL);
1946  else /* don't bother for indexes */
1947  relallvisible = 0;
1948 
1949  if (rd_rel->relpages != (int32) relpages)
1950  {
1951  rd_rel->relpages = (int32) relpages;
1952  dirty = true;
1953  }
1954  if (rd_rel->reltuples != (float4) reltuples)
1955  {
1956  rd_rel->reltuples = (float4) reltuples;
1957  dirty = true;
1958  }
1959  if (rd_rel->relallvisible != (int32) relallvisible)
1960  {
1961  rd_rel->relallvisible = (int32) relallvisible;
1962  dirty = true;
1963  }
1964  }
1965 
1966  /*
1967  * If anything changed, write out the tuple
1968  */
1969  if (dirty)
1970  {
1971  heap_inplace_update(pg_class, tuple);
1972  /* the above sends a cache inval message */
1973  }
1974  else
1975  {
1976  /* no need to change tuple, but force relcache inval anyway */
1978  }
1979 
1980  heap_freetuple(tuple);
1981 
1982  heap_close(pg_class, RowExclusiveLock);
1983 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define RelationRelationId
Definition: pg_class.h:29
uint32 BlockNumber
Definition: block.h:31
#define heap_close(r, l)
Definition: heapam.h:97
void visibilitymap_count(Relation rel, BlockNumber *all_visible, BlockNumber *all_frozen)
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
bool ReindexIsProcessingHeap(Oid heapOid)
Definition: index.c:3666
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1405
float float4
Definition: c.h:374
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1808
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:168
void heap_inplace_update(Relation relation, HeapTuple tuple)
Definition: heapam.c:6246
#define RELKIND_INDEX
Definition: pg_class.h:161
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1269
#define elog
Definition: elog.h:219
#define RelationGetRelid(relation)
Definition: rel.h:416
#define BTEqualStrategyNumber
Definition: stratnum.h:31
double IndexBuildHeapRangeScan ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
bool  allow_sync,
bool  anyvisible,
BlockNumber  start_blockno,
BlockNumber  numblocks,
IndexBuildCallback  callback,
void *  callback_state 
)

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

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

References IndexBuildHeapRangeScan(), and InvalidBlockNumber.

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

2181 {
2182  return IndexBuildHeapRangeScan(heapRelation, indexRelation,
2183  indexInfo, allow_sync,
2184  false,
2185  0, InvalidBlockNumber,
2186  callback, callback_state);
2187 }
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:2200
static void IndexCheckExclusion ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo 
)
static

Definition at line 2645 of file index.c.

References check_exclusion_constraint(), CHECK_FOR_INTERRUPTS, CreateExecutorState(), ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, ExecDropSingleTupleTableSlot(), ExecPrepareQual(), ExecQual(), ExecStoreTuple(), FormIndexDatum(), ForwardScanDirection, FreeExecutorState(), GetLatestSnapshot(), GetPerTupleExprContext, heap_beginscan_strat(), heap_endscan(), heap_getnext(), IndexInfo::ii_ExpressionsState, IndexInfo::ii_Predicate, IndexInfo::ii_PredicateState, INDEX_MAX_KEYS, InvalidBuffer, MakeSingleTupleTableSlot(), MemoryContextReset(), NIL, RegisterSnapshot(), ReindexIsCurrentlyProcessingIndex(), RelationGetDescr, RelationGetRelid, ResetReindexProcessing(), HeapTupleData::t_self, UnregisterSnapshot(), and values.

Referenced by index_build().

2648 {
2649  HeapScanDesc scan;
2650  HeapTuple heapTuple;
2652  bool isnull[INDEX_MAX_KEYS];
2653  ExprState *predicate;
2654  TupleTableSlot *slot;
2655  EState *estate;
2656  ExprContext *econtext;
2657  Snapshot snapshot;
2658 
2659  /*
2660  * If we are reindexing the target index, mark it as no longer being
2661  * reindexed, to forestall an Assert in index_beginscan when we try to use
2662  * the index for probes. This is OK because the index is now fully valid.
2663  */
2666 
2667  /*
2668  * Need an EState for evaluation of index expressions and partial-index
2669  * predicates. Also a slot to hold the current tuple.
2670  */
2671  estate = CreateExecutorState();
2672  econtext = GetPerTupleExprContext(estate);
2673  slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
2674 
2675  /* Arrange for econtext's scan tuple to be the tuple under test */
2676  econtext->ecxt_scantuple = slot;
2677 
2678  /* Set up execution state for predicate, if any. */
2679  predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
2680 
2681  /*
2682  * Scan all live tuples in the base relation.
2683  */
2684  snapshot = RegisterSnapshot(GetLatestSnapshot());
2685  scan = heap_beginscan_strat(heapRelation, /* relation */
2686  snapshot, /* snapshot */
2687  0, /* number of keys */
2688  NULL, /* scan key */
2689  true, /* buffer access strategy OK */
2690  true); /* syncscan OK */
2691 
2692  while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2693  {
2695 
2697 
2698  /* Set up for predicate or expression evaluation */
2699  ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
2700 
2701  /*
2702  * In a partial index, ignore tuples that don't satisfy the predicate.
2703  */
2704  if (predicate != NULL)
2705  {
2706  if (!ExecQual(predicate, econtext))
2707  continue;
2708  }
2709 
2710  /*
2711  * Extract index column values, including computing expressions.
2712  */
2713  FormIndexDatum(indexInfo,
2714  slot,
2715  estate,
2716  values,
2717  isnull);
2718 
2719  /*
2720  * Check that this tuple has no conflicts.
2721  */
2722  check_exclusion_constraint(heapRelation,
2723  indexRelation, indexInfo,
2724  &(heapTuple->t_self), values, isnull,
2725  estate, true);
2726  }
2727 
2728  heap_endscan(scan);
2729  UnregisterSnapshot(snapshot);
2730 
2732 
2733  FreeExecutorState(estate);
2734 
2735  /* These may have been pointing to the now-gone estate */
2736  indexInfo->ii_ExpressionsState = NIL;
2737  indexInfo->ii_PredicateState = NULL;
2738 }
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:1771
#define NIL
Definition: pg_list.h:69
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
List * ii_Predicate
Definition: execnodes.h:138
static bool ReindexIsCurrentlyProcessingIndex(Oid indexOid)
Definition: index.c:3676
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
#define RelationGetDescr(relation)
Definition: rel.h:428
ExprState * ii_PredicateState
Definition: execnodes.h:139
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:203
#define InvalidBuffer
Definition: buf.h:25
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:366
static void ResetReindexProcessing(void)
Definition: index.c:3717
void FreeExecutorState(EState *estate)
Definition: execUtils.c:183
#define GetPerTupleExprContext(estate)
Definition: executor.h:476
List * ii_ExpressionsState
Definition: execnodes.h:137
ItemPointerData t_self
Definition: htup.h:65
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:216
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:465
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:199
EState * CreateExecutorState(void)
Definition: execUtils.c:80
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:905
uintptr_t Datum
Definition: postgres.h:372
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1808
HeapScanDesc heap_beginscan_strat(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, bool allow_strat, bool allow_sync)
Definition: heapam.c:1415
#define INDEX_MAX_KEYS
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:197
Snapshot GetLatestSnapshot(void)
Definition: snapmgr.c:379
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
void check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, Datum *values, bool *isnull, EState *estate, bool newIndex)
Definition: execIndexing.c:863
#define RelationGetRelid(relation)
Definition: rel.h:416
Oid IndexGetRelation ( Oid  indexId,
bool  missing_ok 
)

Definition at line 3281 of file index.c.

References Assert, elog, ERROR, GETSTRUCT, HeapTupleIsValid, INDEXRELID, InvalidOid, ObjectIdGetDatum, ReleaseSysCache(), 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().

3282 {
3283  HeapTuple tuple;
3285  Oid result;
3286 
3287  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
3288  if (!HeapTupleIsValid(tuple))
3289  {
3290  if (missing_ok)
3291  return InvalidOid;
3292  elog(ERROR, "cache lookup failed for index %u", indexId);
3293  }
3294  index = (Form_pg_index) GETSTRUCT(tuple);
3295  Assert(index->indexrelid == indexId);
3296 
3297  result = index->indrelid;
3298  ReleaseSysCache(tuple);
3299  return result;
3300 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:159
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:664
#define elog
Definition: elog.h:219
static void InitializeAttributeOids ( Relation  indexRelation,
int  numatts,
Oid  indexoid 
)
static

Definition at line 489 of file index.c.

References i, RelationGetDescr, and TupleDescAttr.

Referenced by index_create().

492 {
493  TupleDesc tupleDescriptor;
494  int i;
495 
496  tupleDescriptor = RelationGetDescr(indexRelation);
497 
498  for (i = 0; i < numatts; i += 1)
499  TupleDescAttr(tupleDescriptor, i)->attrelid = indexoid;
500 }
#define RelationGetDescr(relation)
Definition: rel.h:428
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
int i
static void itemptr_decode ( ItemPointer  itemptr,
int64  encoded 
)
inlinestatic

Definition at line 2928 of file index.c.

References ItemPointerSet.

Referenced by validate_index_heapscan().

2929 {
2930  BlockNumber block = (BlockNumber) (encoded >> 16);
2931  OffsetNumber offset = (OffsetNumber) (encoded & 0xFFFF);
2932 
2933  ItemPointerSet(itemptr, block, offset);
2934 }
uint32 BlockNumber
Definition: block.h:31
uint16 OffsetNumber
Definition: off.h:24
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:105
static int64 itemptr_encode ( ItemPointer  itemptr)
inlinestatic

Definition at line 2907 of file index.c.

References ItemPointerGetBlockNumber, and ItemPointerGetOffsetNumber.

Referenced by validate_index_callback().

2908 {
2909  BlockNumber block = ItemPointerGetBlockNumber(itemptr);
2910  OffsetNumber offset = ItemPointerGetOffsetNumber(itemptr);
2911  int64 encoded;
2912 
2913  /*
2914  * Use the 16 least significant bits for the offset. 32 adjacent bits are
2915  * used for the block number. Since remaining bits are unused, there
2916  * cannot be negative encoded values (We assume a two's complement
2917  * representation).
2918  */
2919  encoded = ((uint64) block << 16) | (uint16) offset;
2920 
2921  return encoded;
2922 }
uint32 BlockNumber
Definition: block.h:31
uint16 OffsetNumber
Definition: off.h:24
unsigned short uint16
Definition: c.h:257
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
void reindex_index ( Oid  indexId,
bool  skip_constraint_checks,
char  persistence,
int  options 
)

Definition at line 3306 of file index.c.

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

Referenced by reindex_relation(), and ReindexIndex().

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

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

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

Definition at line 3676 of file index.c.

References currentlyReindexedIndex.

Referenced by IndexCheckExclusion().

3677 {
3678  return indexOid == currentlyReindexedIndex;
3679 }
static Oid currentlyReindexedIndex
Definition: index.c:3658
bool ReindexIsProcessingHeap ( Oid  heapOid)

Definition at line 3666 of file index.c.

References currentlyReindexedHeap.

Referenced by index_update_stats().

3667 {
3668  return heapOid == currentlyReindexedHeap;
3669 }
static Oid currentlyReindexedHeap
Definition: index.c:3657
bool ReindexIsProcessingIndex ( Oid  indexOid)

Definition at line 3687 of file index.c.

References currentlyReindexedIndex, and list_member_oid().

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

3688 {
3689  return indexOid == currentlyReindexedIndex ||
3691 }
static List * pendingReindexedIndexes
Definition: index.c:3659
static Oid currentlyReindexedIndex
Definition: index.c:3658
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
static bool relationHasPrimaryKey ( Relation  rel)
static

Definition at line 142 of file index.c.

References elog, ERROR, GETSTRUCT, HeapTupleIsValid, INDEXRELID, lfirst_oid, list_free(), ObjectIdGetDatum, RelationGetIndexList(), ReleaseSysCache(), and SearchSysCache1.

Referenced by index_check_primary_key().

143 {
144  bool result = false;
145  List *indexoidlist;
146  ListCell *indexoidscan;
147 
148  /*
149  * Get the list of index OIDs for the table from the relcache, and look up
150  * each one in the pg_index syscache until we find one marked primary key
151  * (hopefully there isn't more than one such).
152  */
153  indexoidlist = RelationGetIndexList(rel);
154 
155  foreach(indexoidscan, indexoidlist)
156  {
157  Oid indexoid = lfirst_oid(indexoidscan);
158  HeapTuple indexTuple;
159 
160  indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
161  if (!HeapTupleIsValid(indexTuple)) /* should not happen */
162  elog(ERROR, "cache lookup failed for index %u", indexoid);
163  result = ((Form_pg_index) GETSTRUCT(indexTuple))->indisprimary;
164  ReleaseSysCache(indexTuple);
165  if (result)
166  break;
167  }
168 
169  list_free(indexoidlist);
170 
171  return result;
172 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:159
#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 HeapTupleIsValid(tuple)
Definition: htup.h:77
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4357
void list_free(List *list)
Definition: list.c:1133
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
#define lfirst_oid(lc)
Definition: pg_list.h:108
static void RemoveReindexPending ( Oid  indexOid)
static

Definition at line 3744 of file index.c.

References list_delete_oid().

Referenced by SetReindexProcessing().

3745 {
3747  indexOid);
3748 }
static List * pendingReindexedIndexes
Definition: index.c:3659
List * list_delete_oid(List *list, Oid datum)
Definition: list.c:636
static void ResetReindexPending ( void  )
static

Definition at line 3755 of file index.c.

References NIL.

Referenced by reindex_relation().

3756 {
3758 }
#define NIL
Definition: pg_list.h:69
static List * pendingReindexedIndexes
Definition: index.c:3659
static void ResetReindexProcessing ( void  )
static

Definition at line 3717 of file index.c.

References currentlyReindexedHeap, currentlyReindexedIndex, and InvalidOid.

Referenced by IndexCheckExclusion(), and reindex_index().

3718 {
3721 }
static Oid currentlyReindexedHeap
Definition: index.c:3657
static Oid currentlyReindexedIndex
Definition: index.c:3658
#define InvalidOid
Definition: postgres_ext.h:36
static void SetReindexPending ( List indexes)
static

Definition at line 3731 of file index.c.

References elog, ERROR, and list_copy().

Referenced by reindex_relation().

3732 {
3733  /* Reindexing is not re-entrant. */
3735  elog(ERROR, "cannot reindex while reindexing");
3737 }
static List * pendingReindexedIndexes
Definition: index.c:3659
List * list_copy(const List *oldlist)
Definition: list.c:1160
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219
static void SetReindexProcessing ( Oid  heapOid,
Oid  indexOid 
)
static

Definition at line 3700 of file index.c.

References Assert, currentlyReindexedHeap, currentlyReindexedIndex, elog, ERROR, OidIsValid, and RemoveReindexPending().

Referenced by reindex_index().

3701 {
3702  Assert(OidIsValid(heapOid) && OidIsValid(indexOid));
3703  /* Reindexing is not re-entrant. */
3705  elog(ERROR, "cannot reindex while reindexing");
3706  currentlyReindexedHeap = heapOid;
3707  currentlyReindexedIndex = indexOid;
3708  /* Index is no longer "pending" reindex. */
3709  RemoveReindexPending(indexOid);
3710 }
static Oid currentlyReindexedHeap
Definition: index.c:3657
#define OidIsValid(objectId)
Definition: c.h:532
#define ERROR
Definition: elog.h:43
static Oid currentlyReindexedIndex
Definition: index.c:3658
static void RemoveReindexPending(Oid indexOid)
Definition: index.c:3744
#define Assert(condition)
Definition: c.h:664
#define elog
Definition: elog.h:219
static void UpdateIndexRelation ( Oid  indexoid,
Oid  heapoid,
IndexInfo indexInfo,
Oid collationOids,
Oid classOids,
int16 coloptions,
bool  primary,
bool  isexclusion,
bool  immediate,
bool  isvalid 
)
static

Definition at line 552 of file index.c.

References Anum_pg_index_indcheckxmin, Anum_pg_index_indclass, Anum_pg_index_indcollation, Anum_pg_index_indexprs, Anum_pg_index_indexrelid, Anum_pg_index_indimmediate, Anum_pg_index_indisclustered, Anum_pg_index_indisexclusion, Anum_pg_index_indislive, Anum_pg_index_indisprimary, Anum_pg_index_indisready, Anum_pg_index_indisreplident, Anum_pg_index_indisunique, Anum_pg_index_indisvalid, Anum_pg_index_indkey, Anum_pg_index_indnatts, Anum_pg_index_indoption, Anum_pg_index_indpred, Anum_pg_index_indrelid, BoolGetDatum, buildint2vector(), buildoidvector(), CatalogTupleInsert(), CStringGetTextDatum, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), i, IndexInfo::ii_Expressions, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_Predicate, IndexInfo::ii_Unique, IndexRelationId, Int16GetDatum, make_ands_explicit(), MemSet, Natts_pg_index, NIL, nodeToString(), ObjectIdGetDatum, pfree(), PointerGetDatum, RelationGetDescr, RowExclusiveLock, values, and int2vector::values.

Referenced by index_create().

562 {
563  int2vector *indkey;
564  oidvector *indcollation;
565  oidvector *indclass;
566  int2vector *indoption;
567  Datum exprsDatum;
568  Datum predDatum;
570  bool nulls[Natts_pg_index];
571  Relation pg_index;
572  HeapTuple tuple;
573  int i;
574 
575  /*
576  * Copy the index key, opclass, and indoption info into arrays (should we
577  * make the caller pass them like this to start with?)
578  */
579  indkey = buildint2vector(NULL, indexInfo->ii_NumIndexAttrs);
580  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
581  indkey->values[i] = indexInfo->ii_KeyAttrNumbers[i];
582  indcollation = buildoidvector(collationOids, indexInfo->ii_NumIndexAttrs);
583  indclass = buildoidvector(classOids, indexInfo->ii_NumIndexAttrs);
584  indoption = buildint2vector(coloptions, indexInfo->ii_NumIndexAttrs);
585 
586  /*
587  * Convert the index expressions (if any) to a text datum
588  */
589  if (indexInfo->ii_Expressions != NIL)
590  {
591  char *exprsString;
592 
593  exprsString = nodeToString(indexInfo->ii_Expressions);
594  exprsDatum = CStringGetTextDatum(exprsString);
595  pfree(exprsString);
596  }
597  else
598  exprsDatum = (Datum) 0;
599 
600  /*
601  * Convert the index predicate (if any) to a text datum. Note we convert
602  * implicit-AND format to normal explicit-AND for storage.
603  */
604  if (indexInfo->ii_Predicate != NIL)
605  {
606  char *predString;
607 
608  predString = nodeToString(make_ands_explicit(indexInfo->ii_Predicate));
609  predDatum = CStringGetTextDatum(predString);
610  pfree(predString);
611  }
612  else
613  predDatum = (Datum) 0;
614 
615  /*
616  * open the system catalog index relation
617  */
619 
620  /*
621  * Build a pg_index tuple
622  */
623  MemSet(nulls, false, sizeof(nulls));
624 
625  values[Anum_pg_index_indexrelid - 1] = ObjectIdGetDatum(indexoid);
626  values[Anum_pg_index_indrelid - 1] = ObjectIdGetDatum(heapoid);
627  values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs);
628  values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique);
629  values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary);
630  values[Anum_pg_index_indisexclusion - 1] = BoolGetDatum(isexclusion);
631  values[Anum_pg_index_indimmediate - 1] = BoolGetDatum(immediate);
632  values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false);
633  values[Anum_pg_index_indisvalid - 1] = BoolGetDatum(isvalid);
634  values[Anum_pg_index_indcheckxmin - 1] = BoolGetDatum(false);
635  /* we set isvalid and isready the same way */
636  values[Anum_pg_index_indisready - 1] = BoolGetDatum(isvalid);
637  values[Anum_pg_index_indislive - 1] = BoolGetDatum(true);
638  values[Anum_pg_index_indisreplident - 1] = BoolGetDatum(false);
639  values[Anum_pg_index_indkey - 1] = PointerGetDatum(indkey);
640  values[Anum_pg_index_indcollation - 1] = PointerGetDatum(indcollation);
641  values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass);
642  values[Anum_pg_index_indoption - 1] = PointerGetDatum(indoption);
643  values[Anum_pg_index_indexprs - 1] = exprsDatum;
644  if (exprsDatum == (Datum) 0)
645  nulls[Anum_pg_index_indexprs - 1] = true;
646  values[Anum_pg_index_indpred - 1] = predDatum;
647  if (predDatum == (Datum) 0)
648  nulls[Anum_pg_index_indpred - 1] = true;
649 
650  tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls);
651 
652  /*
653  * insert the tuple into the pg_index catalog
654  */
655  CatalogTupleInsert(pg_index, tuple);
656 
657  /*
658  * close the relation and free the tuple
659  */
660  heap_close(pg_index, RowExclusiveLock);
661  heap_freetuple(tuple);
662 }
#define NIL
Definition: pg_list.h:69
Definition: c.h:472
#define Anum_pg_index_indisprimary
Definition: pg_index.h:78
List * ii_Predicate
Definition: execnodes.h:138
#define RelationGetDescr(relation)
Definition: rel.h:428
#define PointerGetDatum(X)
Definition: postgres.h:562
#define IndexRelationId
Definition: pg_index.h:29
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:112
#define Int16GetDatum(X)
Definition: postgres.h:457
#define Anum_pg_index_indclass
Definition: pg_index.h:89
#define MemSet(start, val, len)
Definition: c.h:846
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define heap_close(r, l)
Definition: heapam.h:97
#define Anum_pg_index_indisexclusion
Definition: pg_index.h:79
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define Anum_pg_index_indcheckxmin
Definition: pg_index.h:83
#define Anum_pg_index_indrelid
Definition: pg_index.h:75
Expr * make_ands_explicit(List *andclauses)
Definition: clauses.c:367
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define RowExclusiveLock
Definition: lockdefs.h:38
#define Anum_pg_index_indisready
Definition: pg_index.h:84
#define Anum_pg_index_indislive
Definition: pg_index.h:85
#define Natts_pg_index
Definition: pg_index.h:73
#define Anum_pg_index_indkey
Definition: pg_index.h:87
Definition: c.h:461
uintptr_t Datum
Definition: postgres.h:372
int ii_NumIndexAttrs
Definition: execnodes.h:134
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Anum_pg_index_indisunique
Definition: pg_index.h:77
#define BoolGetDatum(X)
Definition: postgres.h:408
#define Anum_pg_index_indpred
Definition: pg_index.h:92
bool ii_Unique
Definition: execnodes.h:146
List * ii_Expressions
Definition: execnodes.h:136
#define Anum_pg_index_indisreplident
Definition: pg_index.h:86
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:135
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:469
#define Anum_pg_index_indcollation
Definition: pg_index.h:88
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Anum_pg_index_indisvalid
Definition: pg_index.h:82
#define Anum_pg_index_indimmediate
Definition: pg_index.h:80
#define Anum_pg_index_indnatts
Definition: pg_index.h:76
#define Anum_pg_index_indisclustered
Definition: pg_index.h:81
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4255
#define Anum_pg_index_indoption
Definition: pg_index.h:90
#define Anum_pg_index_indexrelid
Definition: pg_index.h:74
#define Anum_pg_index_indexprs
Definition: pg_index.h:91
void validate_index ( Oid  heapId,
Oid  indexId,
Snapshot  snapshot 
)

Definition at line 2805 of file index.c.

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

Referenced by DefineIndex().

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

Definition at line 2940 of file index.c.

References Int64GetDatum(), itemptr_encode(), v_i_state::itups, v_i_state::tuplesort, and tuplesort_putdatum().

Referenced by validate_index().

2941 {
2942  v_i_state *state = (v_i_state *) opaque;
2943  int64 encoded = itemptr_encode(itemptr);
2944 
2945  tuplesort_putdatum(state->tuplesort, Int64GetDatum(encoded), false);
2946  state->itups += 1;
2947  return false; /* never actually delete anything */
2948 }
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
Definition: tuplesort.c:1485
Tuplesortstate * tuplesort
Definition: index.c:82
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
static int64 itemptr_encode(ItemPointer itemptr)
Definition: index.c:2907
Definition: regguts.h:298
double itups
Definition: index.c:84
static void validate_index_heapscan ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
Snapshot  snapshot,
v_i_state state 
)
static

Definition at line 2957 of file index.c.

References Assert, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, CHECK_FOR_INTERRUPTS, CreateExecutorState(), DatumGetInt64, DatumGetPointer, ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, elog, ERROR, ExecDropSingleTupleTableSlot(), ExecPrepareQual(), ExecQual(), ExecStoreTuple(), FormIndexDatum(), ForwardScanDirection, FreeExecutorState(), GetPerTupleExprContext, heap_beginscan_strat(), heap_endscan(), heap_get_root_tuples(), heap_getnext(), HeapTupleIsHeapOnly, v_i_state::htups, IndexInfo::ii_ExpressionsState, IndexInfo::ii_Predicate, IndexInfo::ii_PredicateState, IndexInfo::ii_Unique, index_insert(), INDEX_MAX_KEYS, InvalidBlockNumber, InvalidBuffer, ItemPointerCompare(), ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, ItemPointerSetOffsetNumber, itemptr_decode(), LockBuffer(), MakeSingleTupleTableSlot(), MaxHeapTuplesPerPage, MemoryContextReset(), NIL, OffsetNumberIsValid, OidIsValid, pfree(), RelationData::rd_rel, RelationGetDescr, RelationGetRelationName, HeapScanDescData::rs_cblock, HeapScanDescData::rs_cbuf, HeapTupleData::t_self, v_i_state::tuplesort, tuplesort_getdatum(), v_i_state::tups_inserted, UNIQUE_CHECK_NO, UNIQUE_CHECK_YES, and values.

Referenced by validate_index().

2962 {
2963  HeapScanDesc scan;
2964  HeapTuple heapTuple;
2966  bool isnull[INDEX_MAX_KEYS];
2967  ExprState *predicate;
2968  TupleTableSlot *slot;
2969  EState *estate;
2970  ExprContext *econtext;
2971  BlockNumber root_blkno = InvalidBlockNumber;
2972  OffsetNumber root_offsets[MaxHeapTuplesPerPage];
2973  bool in_index[MaxHeapTuplesPerPage];
2974 
2975  /* state variables for the merge */
2976  ItemPointer indexcursor = NULL;
2977  ItemPointerData decoded;
2978  bool tuplesort_empty = false;
2979 
2980  /*
2981  * sanity checks
2982  */
2983  Assert(OidIsValid(indexRelation->rd_rel->relam));
2984 
2985  /*
2986  * Need an EState for evaluation of index expressions and partial-index
2987  * predicates. Also a slot to hold the current tuple.
2988  */
2989  estate = CreateExecutorState();
2990  econtext = GetPerTupleExprContext(estate);
2991  slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
2992 
2993  /* Arrange for econtext's scan tuple to be the tuple under test */
2994  econtext->ecxt_scantuple = slot;
2995 
2996  /* Set up execution state for predicate, if any. */
2997  predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
2998 
2999  /*
3000  * Prepare for scan of the base relation. We need just those tuples
3001  * satisfying the passed-in reference snapshot. We must disable syncscan
3002  * here, because it's critical that we read from block zero forward to
3003  * match the sorted TIDs.
3004  */
3005  scan = heap_beginscan_strat(heapRelation, /* relation */
3006  snapshot, /* snapshot */
3007  0, /* number of keys */
3008  NULL, /* scan key */
3009  true, /* buffer access strategy OK */
3010  false); /* syncscan not OK */
3011 
3012  /*
3013  * Scan all tuples matching the snapshot.
3014  */
3015  while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
3016  {
3017  ItemPointer heapcursor = &heapTuple->t_self;
3018  ItemPointerData rootTuple;
3019  OffsetNumber root_offnum;
3020 
3022 
3023  state->htups += 1;
3024 
3025  /*
3026  * As commented in IndexBuildHeapScan, we should index heap-only
3027  * tuples under the TIDs of their root tuples; so when we advance onto
3028  * a new heap page, build a map of root item offsets on the page.
3029  *
3030  * This complicates merging against the tuplesort output: we will
3031  * visit the live tuples in order by their offsets, but the root
3032  * offsets that we need to compare against the index contents might be
3033  * ordered differently. So we might have to "look back" within the
3034  * tuplesort output, but only within the current page. We handle that
3035  * by keeping a bool array in_index[] showing all the
3036  * already-passed-over tuplesort output TIDs of the current page. We
3037  * clear that array here, when advancing onto a new heap page.
3038  */
3039  if (scan->rs_cblock != root_blkno)
3040  {
3041  Page page = BufferGetPage(scan->rs_cbuf);
3042 
3044  heap_get_root_tuples(page, root_offsets);
3046 
3047  memset(in_index, 0, sizeof(in_index));
3048 
3049  root_blkno = scan->rs_cblock;
3050  }
3051 
3052  /* Convert actual tuple TID to root TID */
3053  rootTuple = *heapcursor;
3054  root_offnum = ItemPointerGetOffsetNumber(heapcursor);
3055 
3056  if (HeapTupleIsHeapOnly(heapTuple))
3057  {
3058  root_offnum = root_offsets[root_offnum - 1];
3059  if (!OffsetNumberIsValid(root_offnum))
3060  elog(ERROR, "failed to find parent tuple for heap-only tuple at (%u,%u) in table \"%s\"",
3061  ItemPointerGetBlockNumber(heapcursor),
3062  ItemPointerGetOffsetNumber(heapcursor),
3063  RelationGetRelationName(heapRelation));
3064  ItemPointerSetOffsetNumber(&rootTuple, root_offnum);
3065  }
3066 
3067  /*
3068  * "merge" by skipping through the index tuples until we find or pass
3069  * the current root tuple.
3070  */
3071  while (!tuplesort_empty &&
3072  (!indexcursor ||
3073  ItemPointerCompare(indexcursor, &rootTuple) < 0))
3074  {
3075  Datum ts_val;
3076  bool ts_isnull;
3077 
3078  if (indexcursor)
3079  {
3080  /*
3081  * Remember index items seen earlier on the current heap page
3082  */
3083  if (ItemPointerGetBlockNumber(indexcursor) == root_blkno)
3084  in_index[ItemPointerGetOffsetNumber(indexcursor) - 1] = true;
3085  }
3086 
3087  tuplesort_empty = !tuplesort_getdatum(state->tuplesort, true,
3088  &ts_val, &ts_isnull, NULL);
3089  Assert(tuplesort_empty || !ts_isnull);
3090  if (!tuplesort_empty)
3091  {
3092  itemptr_decode(&decoded, DatumGetInt64(ts_val));
3093  indexcursor = &decoded;
3094 
3095  /* If int8 is pass-by-ref, free (encoded) TID Datum memory */
3096 #ifndef USE_FLOAT8_BYVAL
3097  pfree(DatumGetPointer(ts_val));
3098 #endif
3099  }
3100  else
3101  {
3102  /* Be tidy */
3103  indexcursor = NULL;
3104  }
3105  }
3106 
3107  /*
3108  * If the tuplesort has overshot *and* we didn't see a match earlier,
3109  * then this tuple is missing from the index, so insert it.
3110  */
3111  if ((tuplesort_empty ||
3112  ItemPointerCompare(indexcursor, &rootTuple) > 0) &&
3113  !in_index[root_offnum - 1])
3114  {
3116 
3117  /* Set up for predicate or expression evaluation */
3118  ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
3119 
3120  /*
3121  * In a partial index, discard tuples that don't satisfy the
3122  * predicate.
3123  */
3124  if (predicate != NULL)
3125  {
3126  if (!ExecQual(predicate, econtext))
3127  continue;
3128  }
3129 
3130  /*
3131  * For the current heap tuple, extract all the attributes we use
3132  * in this index, and note which are null. This also performs
3133  * evaluation of any expressions needed.
3134  */
3135  FormIndexDatum(indexInfo,
3136  slot,
3137  estate,
3138  values,
3139  isnull);
3140 
3141  /*
3142  * You'd think we should go ahead and build the index tuple here,
3143  * but some index AMs want to do further processing on the data
3144  * first. So pass the values[] and isnull[] arrays, instead.
3145  */
3146 
3147  /*
3148  * If the tuple is already committed dead, you might think we
3149  * could suppress uniqueness checking, but this is no longer true
3150  * in the presence of HOT, because the insert is actually a proxy
3151  * for a uniqueness check on the whole HOT-chain. That is, the
3152  * tuple we have here could be dead because it was already
3153  * HOT-updated, and if so the updating transaction will not have
3154  * thought it should insert index entries. The index AM will
3155  * check the whole HOT-chain and correctly detect a conflict if
3156  * there is one.
3157  */
3158 
3159  index_insert(indexRelation,
3160  values,
3161  isnull,
3162  &rootTuple,
3163  heapRelation,
3164  indexInfo->ii_Unique ?
3166  indexInfo);
3167 
3168  state->tups_inserted += 1;
3169  }
3170  }
3171 
3172  heap_endscan(scan);
3173 
3175 
3176  FreeExecutorState(estate);
3177 
3178  /* These may have been pointing to the now-gone estate */
3179  indexInfo->ii_ExpressionsState = NIL;
3180  indexInfo->ii_PredicateState = NULL;
3181 }
int32 ItemPointerCompare(ItemPointer arg1, ItemPointer arg2)
Definition: itemptr.c:52
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:1771
#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
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, Datum *val, bool *isNull, Datum *abbrev)
Definition: tuplesort.c:2199
BlockNumber rs_cblock
Definition: relscan.h:70
List * ii_Predicate
Definition: execnodes.h:138
static void itemptr_decode(ItemPointer itemptr, int64 encoded)
Definition: index.c:2928
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
#define RelationGetDescr(relation)
Definition: rel.h:428
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
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
uint32 BlockNumber
Definition: block.h:31
double htups
Definition: index.c:84
Form_pg_class rd_rel
Definition: rel.h:114
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:366
#define OidIsValid(objectId)
Definition: c.h:532
Tuplesortstate * tuplesort
Definition: index.c:82
uint16 OffsetNumber
Definition: off.h:24
void FreeExecutorState(EState *estate)
Definition: execUtils.c:183
#define GetPerTupleExprContext(estate)
Definition: executor.h:476
List * ii_ExpressionsState
Definition: execnodes.h:137
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define DatumGetInt64(X)
Definition: postgres.h:613
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:216
#define RelationGetRelationName(relation)
Definition: rel.h:436
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:465
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
uintptr_t Datum
Definition: postgres.h:372
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1808
HeapScanDesc heap_beginscan_strat(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, bool allow_strat, bool allow_sync)
Definition: heapam.c:1415
Buffer rs_cbuf
Definition: relscan.h:71
bool ii_Unique
Definition: execnodes.h:146
#define HeapTupleIsHeapOnly(tuple)
Definition: htup_details.h:686
#define Assert(condition)
Definition: c.h:664
#define INDEX_MAX_KEYS
#define InvalidBlockNumber
Definition: block.h:33
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:197
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
#define DatumGetPointer(X)
Definition: postgres.h:555
#define ItemPointerSetOffsetNumber(pointer, offsetNumber)
Definition: itemptr.h:126
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#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
double tups_inserted
Definition: index.c:84
Pointer Page
Definition: bufpage.h:74
bool index_insert(Relation indexRelation, Datum *values, bool *isnull, ItemPointer heap_t_ctid, Relation heapRelation, IndexUniqueCheck checkUnique, IndexInfo *indexInfo)
Definition: indexam.c:194

Variable Documentation

Oid binary_upgrade_next_index_pg_class_oid = InvalidOid

Definition at line 77 of file index.c.

Referenced by binary_upgrade_set_next_index_pg_class_oid(), and index_create().

Oid currentlyReindexedHeap = InvalidOid
static

Definition at line 3657 of file index.c.

Referenced by ReindexIsProcessingHeap(), ResetReindexProcessing(), and SetReindexProcessing().

Oid currentlyReindexedIndex = InvalidOid
static
List* pendingReindexedIndexes = NIL
static

Definition at line 3659 of file index.c.