00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "postgres.h"
00023
00024 #include <unistd.h>
00025
00026 #include "access/multixact.h"
00027 #include "access/relscan.h"
00028 #include "access/sysattr.h"
00029 #include "access/transam.h"
00030 #include "access/visibilitymap.h"
00031 #include "access/xact.h"
00032 #include "bootstrap/bootstrap.h"
00033 #include "catalog/catalog.h"
00034 #include "catalog/dependency.h"
00035 #include "catalog/heap.h"
00036 #include "catalog/index.h"
00037 #include "catalog/objectaccess.h"
00038 #include "catalog/pg_collation.h"
00039 #include "catalog/pg_constraint.h"
00040 #include "catalog/pg_operator.h"
00041 #include "catalog/pg_opclass.h"
00042 #include "catalog/pg_tablespace.h"
00043 #include "catalog/pg_trigger.h"
00044 #include "catalog/pg_type.h"
00045 #include "catalog/storage.h"
00046 #include "commands/tablecmds.h"
00047 #include "commands/trigger.h"
00048 #include "executor/executor.h"
00049 #include "miscadmin.h"
00050 #include "nodes/makefuncs.h"
00051 #include "nodes/nodeFuncs.h"
00052 #include "optimizer/clauses.h"
00053 #include "parser/parser.h"
00054 #include "storage/bufmgr.h"
00055 #include "storage/lmgr.h"
00056 #include "storage/predicate.h"
00057 #include "storage/procarray.h"
00058 #include "storage/smgr.h"
00059 #include "utils/builtins.h"
00060 #include "utils/fmgroids.h"
00061 #include "utils/guc.h"
00062 #include "utils/inval.h"
00063 #include "utils/lsyscache.h"
00064 #include "utils/memutils.h"
00065 #include "utils/syscache.h"
00066 #include "utils/tuplesort.h"
00067 #include "utils/snapmgr.h"
00068 #include "utils/tqual.h"
00069
00070
00071
00072 Oid binary_upgrade_next_index_pg_class_oid = InvalidOid;
00073
00074
00075 typedef struct
00076 {
00077 Tuplesortstate *tuplesort;
00078
00079 double htups,
00080 itups,
00081 tups_inserted;
00082 } v_i_state;
00083
00084
00085 static bool relationHasPrimaryKey(Relation rel);
00086 static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
00087 IndexInfo *indexInfo,
00088 List *indexColNames,
00089 Oid accessMethodObjectId,
00090 Oid *collationObjectId,
00091 Oid *classObjectId);
00092 static void InitializeAttributeOids(Relation indexRelation,
00093 int numatts, Oid indexoid);
00094 static void AppendAttributeTuples(Relation indexRelation, int numatts);
00095 static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
00096 IndexInfo *indexInfo,
00097 Oid *collationOids,
00098 Oid *classOids,
00099 int16 *coloptions,
00100 bool primary,
00101 bool isexclusion,
00102 bool immediate,
00103 bool isvalid);
00104 static void index_update_stats(Relation rel,
00105 bool hasindex, bool isprimary,
00106 Oid reltoastidxid, double reltuples);
00107 static void IndexCheckExclusion(Relation heapRelation,
00108 Relation indexRelation,
00109 IndexInfo *indexInfo);
00110 static bool validate_index_callback(ItemPointer itemptr, void *opaque);
00111 static void validate_index_heapscan(Relation heapRelation,
00112 Relation indexRelation,
00113 IndexInfo *indexInfo,
00114 Snapshot snapshot,
00115 v_i_state *state);
00116 static bool ReindexIsCurrentlyProcessingIndex(Oid indexOid);
00117 static void SetReindexProcessing(Oid heapOid, Oid indexOid);
00118 static void ResetReindexProcessing(void);
00119 static void SetReindexPending(List *indexes);
00120 static void RemoveReindexPending(Oid indexOid);
00121 static void ResetReindexPending(void);
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 static bool
00135 relationHasPrimaryKey(Relation rel)
00136 {
00137 bool result = false;
00138 List *indexoidlist;
00139 ListCell *indexoidscan;
00140
00141
00142
00143
00144
00145
00146 indexoidlist = RelationGetIndexList(rel);
00147
00148 foreach(indexoidscan, indexoidlist)
00149 {
00150 Oid indexoid = lfirst_oid(indexoidscan);
00151 HeapTuple indexTuple;
00152
00153 indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
00154 if (!HeapTupleIsValid(indexTuple))
00155 elog(ERROR, "cache lookup failed for index %u", indexoid);
00156 result = ((Form_pg_index) GETSTRUCT(indexTuple))->indisprimary;
00157 ReleaseSysCache(indexTuple);
00158 if (result)
00159 break;
00160 }
00161
00162 list_free(indexoidlist);
00163
00164 return result;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 void
00185 index_check_primary_key(Relation heapRel,
00186 IndexInfo *indexInfo,
00187 bool is_alter_table)
00188 {
00189 List *cmds;
00190 int i;
00191
00192
00193
00194
00195
00196
00197
00198 if (is_alter_table &&
00199 relationHasPrimaryKey(heapRel))
00200 {
00201 ereport(ERROR,
00202 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
00203 errmsg("multiple primary keys for table \"%s\" are not allowed",
00204 RelationGetRelationName(heapRel))));
00205 }
00206
00207
00208
00209
00210
00211 cmds = NIL;
00212 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
00213 {
00214 AttrNumber attnum = indexInfo->ii_KeyAttrNumbers[i];
00215 HeapTuple atttuple;
00216 Form_pg_attribute attform;
00217
00218 if (attnum == 0)
00219 ereport(ERROR,
00220 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00221 errmsg("primary keys cannot be expressions")));
00222
00223
00224 if (attnum < 0)
00225 continue;
00226
00227 atttuple = SearchSysCache2(ATTNUM,
00228 ObjectIdGetDatum(RelationGetRelid(heapRel)),
00229 Int16GetDatum(attnum));
00230 if (!HeapTupleIsValid(atttuple))
00231 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
00232 attnum, RelationGetRelid(heapRel));
00233 attform = (Form_pg_attribute) GETSTRUCT(atttuple);
00234
00235 if (!attform->attnotnull)
00236 {
00237
00238 AlterTableCmd *cmd = makeNode(AlterTableCmd);
00239
00240 cmd->subtype = AT_SetNotNull;
00241 cmd->name = pstrdup(NameStr(attform->attname));
00242 cmds = lappend(cmds, cmd);
00243 }
00244
00245 ReleaseSysCache(atttuple);
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 if (cmds)
00259 AlterTableInternal(RelationGetRelid(heapRel), cmds, false);
00260 }
00261
00262
00263
00264
00265
00266
00267 static TupleDesc
00268 ConstructTupleDescriptor(Relation heapRelation,
00269 IndexInfo *indexInfo,
00270 List *indexColNames,
00271 Oid accessMethodObjectId,
00272 Oid *collationObjectId,
00273 Oid *classObjectId)
00274 {
00275 int numatts = indexInfo->ii_NumIndexAttrs;
00276 ListCell *colnames_item = list_head(indexColNames);
00277 ListCell *indexpr_item = list_head(indexInfo->ii_Expressions);
00278 HeapTuple amtuple;
00279 Form_pg_am amform;
00280 TupleDesc heapTupDesc;
00281 TupleDesc indexTupDesc;
00282 int natts;
00283 int i;
00284
00285
00286 amtuple = SearchSysCache1(AMOID,
00287 ObjectIdGetDatum(accessMethodObjectId));
00288 if (!HeapTupleIsValid(amtuple))
00289 elog(ERROR, "cache lookup failed for access method %u",
00290 accessMethodObjectId);
00291 amform = (Form_pg_am) GETSTRUCT(amtuple);
00292
00293
00294 heapTupDesc = RelationGetDescr(heapRelation);
00295 natts = RelationGetForm(heapRelation)->relnatts;
00296
00297
00298
00299
00300 indexTupDesc = CreateTemplateTupleDesc(numatts, false);
00301
00302
00303
00304
00305
00306
00307 for (i = 0; i < numatts; i++)
00308 {
00309 AttrNumber atnum = indexInfo->ii_KeyAttrNumbers[i];
00310 Form_pg_attribute to = indexTupDesc->attrs[i];
00311 HeapTuple tuple;
00312 Form_pg_type typeTup;
00313 Form_pg_opclass opclassTup;
00314 Oid keyType;
00315
00316 if (atnum != 0)
00317 {
00318
00319 Form_pg_attribute from;
00320
00321 if (atnum < 0)
00322 {
00323
00324
00325
00326 from = SystemAttributeDefinition(atnum,
00327 heapRelation->rd_rel->relhasoids);
00328 }
00329 else
00330 {
00331
00332
00333
00334 if (atnum > natts)
00335 elog(ERROR, "invalid column number %d", atnum);
00336 from = heapTupDesc->attrs[AttrNumberGetAttrOffset(atnum)];
00337 }
00338
00339
00340
00341
00342
00343 memcpy(to, from, ATTRIBUTE_FIXED_PART_SIZE);
00344
00345
00346
00347
00348
00349 to->attnum = i + 1;
00350
00351 to->attstattarget = -1;
00352 to->attcacheoff = -1;
00353 to->attnotnull = false;
00354 to->atthasdef = false;
00355 to->attislocal = true;
00356 to->attinhcount = 0;
00357 to->attcollation = collationObjectId[i];
00358 }
00359 else
00360 {
00361
00362 Node *indexkey;
00363
00364 MemSet(to, 0, ATTRIBUTE_FIXED_PART_SIZE);
00365
00366 if (indexpr_item == NULL)
00367 elog(ERROR, "too few entries in indexprs list");
00368 indexkey = (Node *) lfirst(indexpr_item);
00369 indexpr_item = lnext(indexpr_item);
00370
00371
00372
00373
00374 keyType = exprType(indexkey);
00375 tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
00376 if (!HeapTupleIsValid(tuple))
00377 elog(ERROR, "cache lookup failed for type %u", keyType);
00378 typeTup = (Form_pg_type) GETSTRUCT(tuple);
00379
00380
00381
00382
00383 to->attnum = i + 1;
00384 to->atttypid = keyType;
00385 to->attlen = typeTup->typlen;
00386 to->attbyval = typeTup->typbyval;
00387 to->attstorage = typeTup->typstorage;
00388 to->attalign = typeTup->typalign;
00389 to->attstattarget = -1;
00390 to->attcacheoff = -1;
00391 to->atttypmod = -1;
00392 to->attislocal = true;
00393 to->attcollation = collationObjectId[i];
00394
00395 ReleaseSysCache(tuple);
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 CheckAttributeType(NameStr(to->attname),
00407 to->atttypid, to->attcollation,
00408 NIL, false);
00409 }
00410
00411
00412
00413
00414
00415
00416 to->attrelid = InvalidOid;
00417
00418
00419
00420
00421 if (colnames_item == NULL)
00422 elog(ERROR, "too few entries in colnames list");
00423 namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
00424 colnames_item = lnext(colnames_item);
00425
00426
00427
00428
00429
00430 tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(classObjectId[i]));
00431 if (!HeapTupleIsValid(tuple))
00432 elog(ERROR, "cache lookup failed for opclass %u",
00433 classObjectId[i]);
00434 opclassTup = (Form_pg_opclass) GETSTRUCT(tuple);
00435 if (OidIsValid(opclassTup->opckeytype))
00436 keyType = opclassTup->opckeytype;
00437 else
00438 keyType = amform->amkeytype;
00439 ReleaseSysCache(tuple);
00440
00441 if (OidIsValid(keyType) && keyType != to->atttypid)
00442 {
00443
00444 tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
00445 if (!HeapTupleIsValid(tuple))
00446 elog(ERROR, "cache lookup failed for type %u", keyType);
00447 typeTup = (Form_pg_type) GETSTRUCT(tuple);
00448
00449 to->atttypid = keyType;
00450 to->atttypmod = -1;
00451 to->attlen = typeTup->typlen;
00452 to->attbyval = typeTup->typbyval;
00453 to->attalign = typeTup->typalign;
00454 to->attstorage = typeTup->typstorage;
00455
00456 ReleaseSysCache(tuple);
00457 }
00458 }
00459
00460 ReleaseSysCache(amtuple);
00461
00462 return indexTupDesc;
00463 }
00464
00465
00466
00467
00468
00469 static void
00470 InitializeAttributeOids(Relation indexRelation,
00471 int numatts,
00472 Oid indexoid)
00473 {
00474 TupleDesc tupleDescriptor;
00475 int i;
00476
00477 tupleDescriptor = RelationGetDescr(indexRelation);
00478
00479 for (i = 0; i < numatts; i += 1)
00480 tupleDescriptor->attrs[i]->attrelid = indexoid;
00481 }
00482
00483
00484
00485
00486
00487 static void
00488 AppendAttributeTuples(Relation indexRelation, int numatts)
00489 {
00490 Relation pg_attribute;
00491 CatalogIndexState indstate;
00492 TupleDesc indexTupDesc;
00493 int i;
00494
00495
00496
00497
00498 pg_attribute = heap_open(AttributeRelationId, RowExclusiveLock);
00499
00500 indstate = CatalogOpenIndexes(pg_attribute);
00501
00502
00503
00504
00505 indexTupDesc = RelationGetDescr(indexRelation);
00506
00507 for (i = 0; i < numatts; i++)
00508 {
00509
00510
00511
00512
00513 Assert(indexTupDesc->attrs[i]->attnum == i + 1);
00514 Assert(indexTupDesc->attrs[i]->attcacheoff == -1);
00515
00516 InsertPgAttributeTuple(pg_attribute, indexTupDesc->attrs[i], indstate);
00517 }
00518
00519 CatalogCloseIndexes(indstate);
00520
00521 heap_close(pg_attribute, RowExclusiveLock);
00522 }
00523
00524
00525
00526
00527
00528
00529
00530 static void
00531 UpdateIndexRelation(Oid indexoid,
00532 Oid heapoid,
00533 IndexInfo *indexInfo,
00534 Oid *collationOids,
00535 Oid *classOids,
00536 int16 *coloptions,
00537 bool primary,
00538 bool isexclusion,
00539 bool immediate,
00540 bool isvalid)
00541 {
00542 int2vector *indkey;
00543 oidvector *indcollation;
00544 oidvector *indclass;
00545 int2vector *indoption;
00546 Datum exprsDatum;
00547 Datum predDatum;
00548 Datum values[Natts_pg_index];
00549 bool nulls[Natts_pg_index];
00550 Relation pg_index;
00551 HeapTuple tuple;
00552 int i;
00553
00554
00555
00556
00557
00558 indkey = buildint2vector(NULL, indexInfo->ii_NumIndexAttrs);
00559 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
00560 indkey->values[i] = indexInfo->ii_KeyAttrNumbers[i];
00561 indcollation = buildoidvector(collationOids, indexInfo->ii_NumIndexAttrs);
00562 indclass = buildoidvector(classOids, indexInfo->ii_NumIndexAttrs);
00563 indoption = buildint2vector(coloptions, indexInfo->ii_NumIndexAttrs);
00564
00565
00566
00567
00568 if (indexInfo->ii_Expressions != NIL)
00569 {
00570 char *exprsString;
00571
00572 exprsString = nodeToString(indexInfo->ii_Expressions);
00573 exprsDatum = CStringGetTextDatum(exprsString);
00574 pfree(exprsString);
00575 }
00576 else
00577 exprsDatum = (Datum) 0;
00578
00579
00580
00581
00582
00583 if (indexInfo->ii_Predicate != NIL)
00584 {
00585 char *predString;
00586
00587 predString = nodeToString(make_ands_explicit(indexInfo->ii_Predicate));
00588 predDatum = CStringGetTextDatum(predString);
00589 pfree(predString);
00590 }
00591 else
00592 predDatum = (Datum) 0;
00593
00594
00595
00596
00597 pg_index = heap_open(IndexRelationId, RowExclusiveLock);
00598
00599
00600
00601
00602 MemSet(nulls, false, sizeof(nulls));
00603
00604 values[Anum_pg_index_indexrelid - 1] = ObjectIdGetDatum(indexoid);
00605 values[Anum_pg_index_indrelid - 1] = ObjectIdGetDatum(heapoid);
00606 values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs);
00607 values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique);
00608 values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary);
00609 values[Anum_pg_index_indisexclusion - 1] = BoolGetDatum(isexclusion);
00610 values[Anum_pg_index_indimmediate - 1] = BoolGetDatum(immediate);
00611 values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false);
00612 values[Anum_pg_index_indisvalid - 1] = BoolGetDatum(isvalid);
00613 values[Anum_pg_index_indcheckxmin - 1] = BoolGetDatum(false);
00614
00615 values[Anum_pg_index_indisready - 1] = BoolGetDatum(isvalid);
00616 values[Anum_pg_index_indislive - 1] = BoolGetDatum(true);
00617 values[Anum_pg_index_indkey - 1] = PointerGetDatum(indkey);
00618 values[Anum_pg_index_indcollation - 1] = PointerGetDatum(indcollation);
00619 values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass);
00620 values[Anum_pg_index_indoption - 1] = PointerGetDatum(indoption);
00621 values[Anum_pg_index_indexprs - 1] = exprsDatum;
00622 if (exprsDatum == (Datum) 0)
00623 nulls[Anum_pg_index_indexprs - 1] = true;
00624 values[Anum_pg_index_indpred - 1] = predDatum;
00625 if (predDatum == (Datum) 0)
00626 nulls[Anum_pg_index_indpred - 1] = true;
00627
00628 tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls);
00629
00630
00631
00632
00633 simple_heap_insert(pg_index, tuple);
00634
00635
00636 CatalogUpdateIndexes(pg_index, tuple);
00637
00638
00639
00640
00641 heap_close(pg_index, RowExclusiveLock);
00642 heap_freetuple(tuple);
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 Oid
00679 index_create(Relation heapRelation,
00680 const char *indexRelationName,
00681 Oid indexRelationId,
00682 Oid relFileNode,
00683 IndexInfo *indexInfo,
00684 List *indexColNames,
00685 Oid accessMethodObjectId,
00686 Oid tableSpaceId,
00687 Oid *collationObjectId,
00688 Oid *classObjectId,
00689 int16 *coloptions,
00690 Datum reloptions,
00691 bool isprimary,
00692 bool isconstraint,
00693 bool deferrable,
00694 bool initdeferred,
00695 bool allow_system_table_mods,
00696 bool skip_build,
00697 bool concurrent,
00698 bool is_internal)
00699 {
00700 Oid heapRelationId = RelationGetRelid(heapRelation);
00701 Relation pg_class;
00702 Relation indexRelation;
00703 TupleDesc indexTupDesc;
00704 bool shared_relation;
00705 bool mapped_relation;
00706 bool is_exclusion;
00707 Oid namespaceId;
00708 int i;
00709 char relpersistence;
00710
00711 is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
00712
00713 pg_class = heap_open(RelationRelationId, RowExclusiveLock);
00714
00715
00716
00717
00718
00719
00720
00721 namespaceId = RelationGetNamespace(heapRelation);
00722 shared_relation = heapRelation->rd_rel->relisshared;
00723 mapped_relation = RelationIsMapped(heapRelation);
00724 relpersistence = heapRelation->rd_rel->relpersistence;
00725
00726
00727
00728
00729 if (indexInfo->ii_NumIndexAttrs < 1)
00730 elog(ERROR, "must index at least one column");
00731
00732 if (!allow_system_table_mods &&
00733 IsSystemRelation(heapRelation) &&
00734 IsNormalProcessingMode())
00735 ereport(ERROR,
00736 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00737 errmsg("user-defined indexes on system catalog tables are not supported")));
00738
00739
00740
00741
00742
00743 if (concurrent &&
00744 IsSystemRelation(heapRelation))
00745 ereport(ERROR,
00746 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00747 errmsg("concurrent index creation on system catalog tables is not supported")));
00748
00749
00750
00751
00752
00753 if (concurrent && is_exclusion)
00754 ereport(ERROR,
00755 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00756 errmsg_internal("concurrent index creation for exclusion constraints is not supported")));
00757
00758
00759
00760
00761
00762 if (shared_relation && !IsBootstrapProcessingMode())
00763 ereport(ERROR,
00764 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00765 errmsg("shared indexes cannot be created after initdb")));
00766
00767
00768
00769
00770 if (shared_relation && tableSpaceId != GLOBALTABLESPACE_OID)
00771 elog(ERROR, "shared relations must be placed in pg_global tablespace");
00772
00773 if (get_relname_relid(indexRelationName, namespaceId))
00774 ereport(ERROR,
00775 (errcode(ERRCODE_DUPLICATE_TABLE),
00776 errmsg("relation \"%s\" already exists",
00777 indexRelationName)));
00778
00779
00780
00781
00782 indexTupDesc = ConstructTupleDescriptor(heapRelation,
00783 indexInfo,
00784 indexColNames,
00785 accessMethodObjectId,
00786 collationObjectId,
00787 classObjectId);
00788
00789
00790
00791
00792
00793
00794
00795 if (!OidIsValid(indexRelationId))
00796 {
00797
00798
00799
00800
00801 if (IsBinaryUpgrade &&
00802 OidIsValid(binary_upgrade_next_index_pg_class_oid))
00803 {
00804 indexRelationId = binary_upgrade_next_index_pg_class_oid;
00805 binary_upgrade_next_index_pg_class_oid = InvalidOid;
00806 }
00807 else
00808 {
00809 indexRelationId =
00810 GetNewRelFileNode(tableSpaceId, pg_class, relpersistence);
00811 }
00812 }
00813
00814
00815
00816
00817
00818
00819 indexRelation = heap_create(indexRelationName,
00820 namespaceId,
00821 tableSpaceId,
00822 indexRelationId,
00823 relFileNode,
00824 indexTupDesc,
00825 RELKIND_INDEX,
00826 relpersistence,
00827 shared_relation,
00828 mapped_relation);
00829
00830 Assert(indexRelationId == RelationGetRelid(indexRelation));
00831
00832
00833
00834
00835
00836
00837 LockRelation(indexRelation, AccessExclusiveLock);
00838
00839
00840
00841
00842
00843
00844
00845 indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
00846 indexRelation->rd_rel->relam = accessMethodObjectId;
00847 indexRelation->rd_rel->relhasoids = false;
00848
00849
00850
00851
00852 InsertPgClassTuple(pg_class, indexRelation,
00853 RelationGetRelid(indexRelation),
00854 (Datum) 0,
00855 reloptions);
00856
00857
00858 heap_close(pg_class, RowExclusiveLock);
00859
00860
00861
00862
00863
00864 InitializeAttributeOids(indexRelation,
00865 indexInfo->ii_NumIndexAttrs,
00866 indexRelationId);
00867
00868
00869
00870
00871 AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs);
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo,
00882 collationObjectId, classObjectId, coloptions,
00883 isprimary, is_exclusion,
00884 !deferrable,
00885 !concurrent);
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901 if (!IsBootstrapProcessingMode())
00902 {
00903 ObjectAddress myself,
00904 referenced;
00905
00906 myself.classId = RelationRelationId;
00907 myself.objectId = indexRelationId;
00908 myself.objectSubId = 0;
00909
00910 if (isconstraint)
00911 {
00912 char constraintType;
00913
00914 if (isprimary)
00915 constraintType = CONSTRAINT_PRIMARY;
00916 else if (indexInfo->ii_Unique)
00917 constraintType = CONSTRAINT_UNIQUE;
00918 else if (is_exclusion)
00919 constraintType = CONSTRAINT_EXCLUSION;
00920 else
00921 {
00922 elog(ERROR, "constraint must be PRIMARY, UNIQUE or EXCLUDE");
00923 constraintType = 0;
00924 }
00925
00926 index_constraint_create(heapRelation,
00927 indexRelationId,
00928 indexInfo,
00929 indexRelationName,
00930 constraintType,
00931 deferrable,
00932 initdeferred,
00933 false,
00934 false,
00935 false,
00936 allow_system_table_mods,
00937 is_internal);
00938 }
00939 else
00940 {
00941 bool have_simple_col = false;
00942
00943
00944 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
00945 {
00946 if (indexInfo->ii_KeyAttrNumbers[i] != 0)
00947 {
00948 referenced.classId = RelationRelationId;
00949 referenced.objectId = heapRelationId;
00950 referenced.objectSubId = indexInfo->ii_KeyAttrNumbers[i];
00951
00952 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
00953
00954 have_simple_col = true;
00955 }
00956 }
00957
00958
00959
00960
00961
00962
00963
00964 if (!have_simple_col)
00965 {
00966 referenced.classId = RelationRelationId;
00967 referenced.objectId = heapRelationId;
00968 referenced.objectSubId = 0;
00969
00970 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
00971 }
00972
00973
00974 Assert(!deferrable);
00975 Assert(!initdeferred);
00976 }
00977
00978
00979
00980 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
00981 {
00982 if (OidIsValid(collationObjectId[i]) &&
00983 collationObjectId[i] != DEFAULT_COLLATION_OID)
00984 {
00985 referenced.classId = CollationRelationId;
00986 referenced.objectId = collationObjectId[i];
00987 referenced.objectSubId = 0;
00988
00989 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00990 }
00991 }
00992
00993
00994 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
00995 {
00996 referenced.classId = OperatorClassRelationId;
00997 referenced.objectId = classObjectId[i];
00998 referenced.objectSubId = 0;
00999
01000 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
01001 }
01002
01003
01004 if (indexInfo->ii_Expressions)
01005 {
01006 recordDependencyOnSingleRelExpr(&myself,
01007 (Node *) indexInfo->ii_Expressions,
01008 heapRelationId,
01009 DEPENDENCY_NORMAL,
01010 DEPENDENCY_AUTO);
01011 }
01012
01013
01014 if (indexInfo->ii_Predicate)
01015 {
01016 recordDependencyOnSingleRelExpr(&myself,
01017 (Node *) indexInfo->ii_Predicate,
01018 heapRelationId,
01019 DEPENDENCY_NORMAL,
01020 DEPENDENCY_AUTO);
01021 }
01022 }
01023 else
01024 {
01025
01026 Assert(!isconstraint);
01027 Assert(!deferrable);
01028 Assert(!initdeferred);
01029 }
01030
01031
01032 InvokeObjectPostCreateHookArg(RelationRelationId,
01033 indexRelationId, 0, is_internal);
01034
01035
01036
01037
01038
01039 CommandCounterIncrement();
01040
01041
01042
01043
01044
01045
01046
01047 if (IsBootstrapProcessingMode())
01048 RelationInitIndexAccessInfo(indexRelation);
01049 else
01050 Assert(indexRelation->rd_indexcxt != NULL);
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 if (IsBootstrapProcessingMode())
01061 {
01062 index_register(heapRelationId, indexRelationId, indexInfo);
01063 }
01064 else if (skip_build)
01065 {
01066
01067
01068
01069
01070
01071 index_update_stats(heapRelation,
01072 true,
01073 isprimary,
01074 InvalidOid,
01075 -1.0);
01076
01077 CommandCounterIncrement();
01078 }
01079 else
01080 {
01081 index_build(heapRelation, indexRelation, indexInfo, isprimary, false);
01082 }
01083
01084
01085
01086
01087
01088 index_close(indexRelation, NoLock);
01089
01090 return indexRelationId;
01091 }
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113 void
01114 index_constraint_create(Relation heapRelation,
01115 Oid indexRelationId,
01116 IndexInfo *indexInfo,
01117 const char *constraintName,
01118 char constraintType,
01119 bool deferrable,
01120 bool initdeferred,
01121 bool mark_as_primary,
01122 bool update_pgindex,
01123 bool remove_old_dependencies,
01124 bool allow_system_table_mods,
01125 bool is_internal)
01126 {
01127 Oid namespaceId = RelationGetNamespace(heapRelation);
01128 ObjectAddress myself,
01129 referenced;
01130 Oid conOid;
01131
01132
01133 Assert(!IsBootstrapProcessingMode());
01134
01135
01136 if (!allow_system_table_mods &&
01137 IsSystemRelation(heapRelation) &&
01138 IsNormalProcessingMode())
01139 ereport(ERROR,
01140 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01141 errmsg("user-defined indexes on system catalog tables are not supported")));
01142
01143
01144 if (indexInfo->ii_Expressions &&
01145 constraintType != CONSTRAINT_EXCLUSION)
01146 elog(ERROR, "constraints cannot have index expressions");
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157 if (remove_old_dependencies)
01158 deleteDependencyRecordsForClass(RelationRelationId, indexRelationId,
01159 RelationRelationId, DEPENDENCY_AUTO);
01160
01161
01162
01163
01164 conOid = CreateConstraintEntry(constraintName,
01165 namespaceId,
01166 constraintType,
01167 deferrable,
01168 initdeferred,
01169 true,
01170 RelationGetRelid(heapRelation),
01171 indexInfo->ii_KeyAttrNumbers,
01172 indexInfo->ii_NumIndexAttrs,
01173 InvalidOid,
01174 indexRelationId,
01175 InvalidOid,
01176 NULL,
01177 NULL,
01178 NULL,
01179 NULL,
01180 0,
01181 ' ',
01182 ' ',
01183 ' ',
01184 indexInfo->ii_ExclusionOps,
01185 NULL,
01186 NULL,
01187 NULL,
01188 true,
01189 0,
01190 true,
01191 is_internal);
01192
01193
01194
01195
01196
01197
01198
01199 myself.classId = RelationRelationId;
01200 myself.objectId = indexRelationId;
01201 myself.objectSubId = 0;
01202
01203 referenced.classId = ConstraintRelationId;
01204 referenced.objectId = conOid;
01205 referenced.objectSubId = 0;
01206
01207 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
01208
01209
01210
01211
01212
01213
01214 if (deferrable)
01215 {
01216 RangeVar *heapRel;
01217 CreateTrigStmt *trigger;
01218
01219 heapRel = makeRangeVar(get_namespace_name(namespaceId),
01220 pstrdup(RelationGetRelationName(heapRelation)),
01221 -1);
01222
01223 trigger = makeNode(CreateTrigStmt);
01224 trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ?
01225 "PK_ConstraintTrigger" :
01226 "Unique_ConstraintTrigger";
01227 trigger->relation = heapRel;
01228 trigger->funcname = SystemFuncName("unique_key_recheck");
01229 trigger->args = NIL;
01230 trigger->row = true;
01231 trigger->timing = TRIGGER_TYPE_AFTER;
01232 trigger->events = TRIGGER_TYPE_INSERT | TRIGGER_TYPE_UPDATE;
01233 trigger->columns = NIL;
01234 trigger->whenClause = NULL;
01235 trigger->isconstraint = true;
01236 trigger->deferrable = true;
01237 trigger->initdeferred = initdeferred;
01238 trigger->constrrel = NULL;
01239
01240 (void) CreateTrigger(trigger, NULL, conOid, indexRelationId, true);
01241 }
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252 if (mark_as_primary)
01253 index_update_stats(heapRelation,
01254 true,
01255 true,
01256 InvalidOid,
01257 -1.0);
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269 if (update_pgindex && (mark_as_primary || deferrable))
01270 {
01271 Relation pg_index;
01272 HeapTuple indexTuple;
01273 Form_pg_index indexForm;
01274 bool dirty = false;
01275
01276 pg_index = heap_open(IndexRelationId, RowExclusiveLock);
01277
01278 indexTuple = SearchSysCacheCopy1(INDEXRELID,
01279 ObjectIdGetDatum(indexRelationId));
01280 if (!HeapTupleIsValid(indexTuple))
01281 elog(ERROR, "cache lookup failed for index %u", indexRelationId);
01282 indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
01283
01284 if (mark_as_primary && !indexForm->indisprimary)
01285 {
01286 indexForm->indisprimary = true;
01287 dirty = true;
01288 }
01289
01290 if (deferrable && indexForm->indimmediate)
01291 {
01292 indexForm->indimmediate = false;
01293 dirty = true;
01294 }
01295
01296 if (dirty)
01297 {
01298 simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
01299 CatalogUpdateIndexes(pg_index, indexTuple);
01300
01301 InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
01302 InvalidOid, is_internal);
01303 }
01304
01305 heap_freetuple(indexTuple);
01306 heap_close(pg_index, RowExclusiveLock);
01307 }
01308 }
01309
01310
01311
01312
01313
01314
01315
01316 void
01317 index_drop(Oid indexId, bool concurrent)
01318 {
01319 Oid heapId;
01320 Relation userHeapRelation;
01321 Relation userIndexRelation;
01322 Relation indexRelation;
01323 HeapTuple tuple;
01324 bool hasexprs;
01325 LockRelId heaprelid,
01326 indexrelid;
01327 LOCKTAG heaplocktag;
01328 LOCKMODE lockmode;
01329 VirtualTransactionId *old_lockholders;
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 heapId = IndexGetRelation(indexId, false);
01350 lockmode = concurrent ? ShareUpdateExclusiveLock : AccessExclusiveLock;
01351 userHeapRelation = heap_open(heapId, lockmode);
01352 userIndexRelation = index_open(indexId, lockmode);
01353
01354
01355
01356
01357
01358 CheckTableNotInUse(userIndexRelation, "DROP INDEX");
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391 if (concurrent)
01392 {
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406 if (GetTopTransactionIdIfAny() != InvalidTransactionId)
01407 ereport(ERROR,
01408 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01409 errmsg("DROP INDEX CONCURRENTLY must be first action in transaction")));
01410
01411
01412
01413
01414 index_set_state_flags(indexId, INDEX_DROP_CLEAR_VALID);
01415
01416
01417
01418
01419
01420
01421 CacheInvalidateRelcache(userHeapRelation);
01422
01423
01424 heaprelid = userHeapRelation->rd_lockInfo.lockRelId;
01425 SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
01426 indexrelid = userIndexRelation->rd_lockInfo.lockRelId;
01427
01428 heap_close(userHeapRelation, NoLock);
01429 index_close(userIndexRelation, NoLock);
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442 LockRelationIdForSession(&heaprelid, ShareUpdateExclusiveLock);
01443 LockRelationIdForSession(&indexrelid, ShareUpdateExclusiveLock);
01444
01445 PopActiveSnapshot();
01446 CommitTransactionCommand();
01447 StartTransactionCommand();
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468 old_lockholders = GetLockConflicts(&heaplocktag, AccessExclusiveLock);
01469
01470 while (VirtualTransactionIdIsValid(*old_lockholders))
01471 {
01472 VirtualXactLock(*old_lockholders, true);
01473 old_lockholders++;
01474 }
01475
01476
01477
01478
01479
01480
01481
01482 userHeapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
01483 userIndexRelation = index_open(indexId, ShareUpdateExclusiveLock);
01484 TransferPredicateLocksToHeapRelation(userIndexRelation);
01485
01486
01487
01488
01489
01490
01491
01492 index_set_state_flags(indexId, INDEX_DROP_SET_DEAD);
01493
01494
01495
01496
01497
01498
01499 CacheInvalidateRelcache(userHeapRelation);
01500
01501
01502
01503
01504 heap_close(userHeapRelation, NoLock);
01505 index_close(userIndexRelation, NoLock);
01506
01507
01508
01509
01510
01511 CommitTransactionCommand();
01512 StartTransactionCommand();
01513
01514
01515
01516
01517
01518 old_lockholders = GetLockConflicts(&heaplocktag, AccessExclusiveLock);
01519
01520 while (VirtualTransactionIdIsValid(*old_lockholders))
01521 {
01522 VirtualXactLock(*old_lockholders, true);
01523 old_lockholders++;
01524 }
01525
01526
01527
01528
01529
01530
01531
01532
01533 userHeapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
01534 userIndexRelation = index_open(indexId, AccessExclusiveLock);
01535 }
01536 else
01537 {
01538
01539 TransferPredicateLocksToHeapRelation(userIndexRelation);
01540 }
01541
01542
01543
01544
01545 RelationDropStorage(userIndexRelation);
01546
01547
01548
01549
01550
01551
01552 index_close(userIndexRelation, NoLock);
01553
01554 RelationForgetRelation(indexId);
01555
01556
01557
01558
01559 indexRelation = heap_open(IndexRelationId, RowExclusiveLock);
01560
01561 tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
01562 if (!HeapTupleIsValid(tuple))
01563 elog(ERROR, "cache lookup failed for index %u", indexId);
01564
01565 hasexprs = !heap_attisnull(tuple, Anum_pg_index_indexprs);
01566
01567 simple_heap_delete(indexRelation, &tuple->t_self);
01568
01569 ReleaseSysCache(tuple);
01570 heap_close(indexRelation, RowExclusiveLock);
01571
01572
01573
01574
01575
01576 if (hasexprs)
01577 RemoveStatistics(indexId, 0);
01578
01579
01580
01581
01582 DeleteAttributeTuples(indexId);
01583
01584
01585
01586
01587 DeleteRelationTuple(indexId);
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597 CacheInvalidateRelcache(userHeapRelation);
01598
01599
01600
01601
01602 heap_close(userHeapRelation, NoLock);
01603
01604
01605
01606
01607 if (concurrent)
01608 {
01609 UnlockRelationIdForSession(&heaprelid, ShareUpdateExclusiveLock);
01610 UnlockRelationIdForSession(&indexrelid, ShareUpdateExclusiveLock);
01611 }
01612 }
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629 IndexInfo *
01630 BuildIndexInfo(Relation index)
01631 {
01632 IndexInfo *ii = makeNode(IndexInfo);
01633 Form_pg_index indexStruct = index->rd_index;
01634 int i;
01635 int numKeys;
01636
01637
01638 numKeys = indexStruct->indnatts;
01639 if (numKeys < 1 || numKeys > INDEX_MAX_KEYS)
01640 elog(ERROR, "invalid indnatts %d for index %u",
01641 numKeys, RelationGetRelid(index));
01642 ii->ii_NumIndexAttrs = numKeys;
01643 for (i = 0; i < numKeys; i++)
01644 ii->ii_KeyAttrNumbers[i] = indexStruct->indkey.values[i];
01645
01646
01647 ii->ii_Expressions = RelationGetIndexExpressions(index);
01648 ii->ii_ExpressionsState = NIL;
01649
01650
01651 ii->ii_Predicate = RelationGetIndexPredicate(index);
01652 ii->ii_PredicateState = NIL;
01653
01654
01655 if (indexStruct->indisexclusion)
01656 {
01657 RelationGetExclusionInfo(index,
01658 &ii->ii_ExclusionOps,
01659 &ii->ii_ExclusionProcs,
01660 &ii->ii_ExclusionStrats);
01661 }
01662 else
01663 {
01664 ii->ii_ExclusionOps = NULL;
01665 ii->ii_ExclusionProcs = NULL;
01666 ii->ii_ExclusionStrats = NULL;
01667 }
01668
01669
01670 ii->ii_Unique = indexStruct->indisunique;
01671 ii->ii_ReadyForInserts = IndexIsReady(indexStruct);
01672
01673
01674 ii->ii_Concurrent = false;
01675 ii->ii_BrokenHotChain = false;
01676
01677 return ii;
01678 }
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699 void
01700 FormIndexDatum(IndexInfo *indexInfo,
01701 TupleTableSlot *slot,
01702 EState *estate,
01703 Datum *values,
01704 bool *isnull)
01705 {
01706 ListCell *indexpr_item;
01707 int i;
01708
01709 if (indexInfo->ii_Expressions != NIL &&
01710 indexInfo->ii_ExpressionsState == NIL)
01711 {
01712
01713 indexInfo->ii_ExpressionsState = (List *)
01714 ExecPrepareExpr((Expr *) indexInfo->ii_Expressions,
01715 estate);
01716
01717 Assert(GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
01718 }
01719 indexpr_item = list_head(indexInfo->ii_ExpressionsState);
01720
01721 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
01722 {
01723 int keycol = indexInfo->ii_KeyAttrNumbers[i];
01724 Datum iDatum;
01725 bool isNull;
01726
01727 if (keycol != 0)
01728 {
01729
01730
01731
01732
01733 iDatum = slot_getattr(slot, keycol, &isNull);
01734 }
01735 else
01736 {
01737
01738
01739
01740 if (indexpr_item == NULL)
01741 elog(ERROR, "wrong number of index expressions");
01742 iDatum = ExecEvalExprSwitchContext((ExprState *) lfirst(indexpr_item),
01743 GetPerTupleExprContext(estate),
01744 &isNull,
01745 NULL);
01746 indexpr_item = lnext(indexpr_item);
01747 }
01748 values[i] = iDatum;
01749 isnull[i] = isNull;
01750 }
01751
01752 if (indexpr_item != NULL)
01753 elog(ERROR, "wrong number of index expressions");
01754 }
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781 static void
01782 index_update_stats(Relation rel,
01783 bool hasindex, bool isprimary,
01784 Oid reltoastidxid, double reltuples)
01785 {
01786 Oid relid = RelationGetRelid(rel);
01787 Relation pg_class;
01788 HeapTuple tuple;
01789 Form_pg_class rd_rel;
01790 bool dirty;
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 pg_class = heap_open(RelationRelationId, RowExclusiveLock);
01829
01830
01831
01832
01833
01834
01835 if (IsBootstrapProcessingMode() ||
01836 ReindexIsProcessingHeap(RelationRelationId))
01837 {
01838
01839 HeapScanDesc pg_class_scan;
01840 ScanKeyData key[1];
01841
01842 ScanKeyInit(&key[0],
01843 ObjectIdAttributeNumber,
01844 BTEqualStrategyNumber, F_OIDEQ,
01845 ObjectIdGetDatum(relid));
01846
01847 pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key);
01848 tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
01849 tuple = heap_copytuple(tuple);
01850 heap_endscan(pg_class_scan);
01851 }
01852 else
01853 {
01854
01855 tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
01856 }
01857
01858 if (!HeapTupleIsValid(tuple))
01859 elog(ERROR, "could not find tuple for relation %u", relid);
01860 rd_rel = (Form_pg_class) GETSTRUCT(tuple);
01861
01862
01863
01864 dirty = false;
01865 if (rd_rel->relhasindex != hasindex)
01866 {
01867 rd_rel->relhasindex = hasindex;
01868 dirty = true;
01869 }
01870 if (isprimary)
01871 {
01872 if (!rd_rel->relhaspkey)
01873 {
01874 rd_rel->relhaspkey = true;
01875 dirty = true;
01876 }
01877 }
01878 if (OidIsValid(reltoastidxid))
01879 {
01880 Assert(rd_rel->relkind == RELKIND_TOASTVALUE);
01881 if (rd_rel->reltoastidxid != reltoastidxid)
01882 {
01883 rd_rel->reltoastidxid = reltoastidxid;
01884 dirty = true;
01885 }
01886 }
01887
01888 if (reltuples >= 0)
01889 {
01890 BlockNumber relpages = RelationGetNumberOfBlocks(rel);
01891 BlockNumber relallvisible;
01892
01893 if (rd_rel->relkind != RELKIND_INDEX)
01894 relallvisible = visibilitymap_count(rel);
01895 else
01896 relallvisible = 0;
01897
01898 if (rd_rel->relpages != (int32) relpages)
01899 {
01900 rd_rel->relpages = (int32) relpages;
01901 dirty = true;
01902 }
01903 if (rd_rel->reltuples != (float4) reltuples)
01904 {
01905 rd_rel->reltuples = (float4) reltuples;
01906 dirty = true;
01907 }
01908 if (rd_rel->relallvisible != (int32) relallvisible)
01909 {
01910 rd_rel->relallvisible = (int32) relallvisible;
01911 dirty = true;
01912 }
01913 }
01914
01915
01916
01917
01918 if (dirty)
01919 {
01920 heap_inplace_update(pg_class, tuple);
01921
01922 }
01923 else
01924 {
01925
01926 CacheInvalidateRelcacheByTuple(tuple);
01927 }
01928
01929 heap_freetuple(tuple);
01930
01931 heap_close(pg_class, RowExclusiveLock);
01932 }
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954 void
01955 index_build(Relation heapRelation,
01956 Relation indexRelation,
01957 IndexInfo *indexInfo,
01958 bool isprimary,
01959 bool isreindex)
01960 {
01961 RegProcedure procedure;
01962 IndexBuildResult *stats;
01963 Oid save_userid;
01964 int save_sec_context;
01965 int save_nestlevel;
01966
01967
01968
01969
01970 Assert(RelationIsValid(indexRelation));
01971 Assert(PointerIsValid(indexRelation->rd_am));
01972
01973 procedure = indexRelation->rd_am->ambuild;
01974 Assert(RegProcedureIsValid(procedure));
01975
01976 ereport(DEBUG1,
01977 (errmsg("building index \"%s\" on table \"%s\"",
01978 RelationGetRelationName(indexRelation),
01979 RelationGetRelationName(heapRelation))));
01980
01981
01982
01983
01984
01985
01986 GetUserIdAndSecContext(&save_userid, &save_sec_context);
01987 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
01988 save_sec_context | SECURITY_RESTRICTED_OPERATION);
01989 save_nestlevel = NewGUCNestLevel();
01990
01991
01992
01993
01994 stats = (IndexBuildResult *)
01995 DatumGetPointer(OidFunctionCall3(procedure,
01996 PointerGetDatum(heapRelation),
01997 PointerGetDatum(indexRelation),
01998 PointerGetDatum(indexInfo)));
01999 Assert(PointerIsValid(stats));
02000
02001
02002
02003
02004
02005
02006
02007
02008 if (heapRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
02009 !smgrexists(indexRelation->rd_smgr, INIT_FORKNUM))
02010 {
02011 RegProcedure ambuildempty = indexRelation->rd_am->ambuildempty;
02012
02013 RelationOpenSmgr(indexRelation);
02014 smgrcreate(indexRelation->rd_smgr, INIT_FORKNUM, false);
02015 OidFunctionCall1(ambuildempty, PointerGetDatum(indexRelation));
02016 }
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041 if (indexInfo->ii_BrokenHotChain && !isreindex &&
02042 !indexInfo->ii_Concurrent)
02043 {
02044 Oid indexId = RelationGetRelid(indexRelation);
02045 Relation pg_index;
02046 HeapTuple indexTuple;
02047 Form_pg_index indexForm;
02048
02049 pg_index = heap_open(IndexRelationId, RowExclusiveLock);
02050
02051 indexTuple = SearchSysCacheCopy1(INDEXRELID,
02052 ObjectIdGetDatum(indexId));
02053 if (!HeapTupleIsValid(indexTuple))
02054 elog(ERROR, "cache lookup failed for index %u", indexId);
02055 indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
02056
02057
02058 Assert(!indexForm->indcheckxmin);
02059
02060 indexForm->indcheckxmin = true;
02061 simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
02062 CatalogUpdateIndexes(pg_index, indexTuple);
02063
02064 heap_freetuple(indexTuple);
02065 heap_close(pg_index, RowExclusiveLock);
02066 }
02067
02068
02069
02070
02071 index_update_stats(heapRelation,
02072 true,
02073 isprimary,
02074 (heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ?
02075 RelationGetRelid(indexRelation) : InvalidOid,
02076 stats->heap_tuples);
02077
02078 index_update_stats(indexRelation,
02079 false,
02080 false,
02081 InvalidOid,
02082 stats->index_tuples);
02083
02084
02085 CommandCounterIncrement();
02086
02087
02088
02089
02090
02091
02092
02093 if (indexInfo->ii_ExclusionOps != NULL)
02094 IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
02095
02096
02097 AtEOXact_GUC(false, save_nestlevel);
02098
02099
02100 SetUserIdAndSecContext(save_userid, save_sec_context);
02101 }
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127 double
02128 IndexBuildHeapScan(Relation heapRelation,
02129 Relation indexRelation,
02130 IndexInfo *indexInfo,
02131 bool allow_sync,
02132 IndexBuildCallback callback,
02133 void *callback_state)
02134 {
02135 bool is_system_catalog;
02136 bool checking_uniqueness;
02137 HeapScanDesc scan;
02138 HeapTuple heapTuple;
02139 Datum values[INDEX_MAX_KEYS];
02140 bool isnull[INDEX_MAX_KEYS];
02141 double reltuples;
02142 List *predicate;
02143 TupleTableSlot *slot;
02144 EState *estate;
02145 ExprContext *econtext;
02146 Snapshot snapshot;
02147 TransactionId OldestXmin;
02148 BlockNumber root_blkno = InvalidBlockNumber;
02149 OffsetNumber root_offsets[MaxHeapTuplesPerPage];
02150
02151
02152
02153
02154 Assert(OidIsValid(indexRelation->rd_rel->relam));
02155
02156
02157 is_system_catalog = IsSystemRelation(heapRelation);
02158
02159
02160 checking_uniqueness = (indexInfo->ii_Unique ||
02161 indexInfo->ii_ExclusionOps != NULL);
02162
02163
02164
02165
02166
02167 estate = CreateExecutorState();
02168 econtext = GetPerTupleExprContext(estate);
02169 slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
02170
02171
02172 econtext->ecxt_scantuple = slot;
02173
02174
02175 predicate = (List *)
02176 ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
02177 estate);
02178
02179
02180
02181
02182
02183
02184
02185
02186 if (IsBootstrapProcessingMode())
02187 {
02188 snapshot = SnapshotNow;
02189 OldestXmin = InvalidTransactionId;
02190 }
02191 else if (indexInfo->ii_Concurrent)
02192 {
02193 snapshot = RegisterSnapshot(GetTransactionSnapshot());
02194 OldestXmin = InvalidTransactionId;
02195 }
02196 else
02197 {
02198 snapshot = SnapshotAny;
02199
02200 OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared, true);
02201 }
02202
02203 scan = heap_beginscan_strat(heapRelation,
02204 snapshot,
02205 0,
02206 NULL,
02207 true,
02208 allow_sync);
02209
02210 reltuples = 0;
02211
02212
02213
02214
02215 while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
02216 {
02217 bool tupleIsAlive;
02218
02219 CHECK_FOR_INTERRUPTS();
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246 if (scan->rs_cblock != root_blkno)
02247 {
02248 Page page = BufferGetPage(scan->rs_cbuf);
02249
02250 LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
02251 heap_get_root_tuples(page, root_offsets);
02252 LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
02253
02254 root_blkno = scan->rs_cblock;
02255 }
02256
02257 if (snapshot == SnapshotAny)
02258 {
02259
02260 bool indexIt;
02261 TransactionId xwait;
02262
02263 recheck:
02264
02265
02266
02267
02268
02269
02270
02271 LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
02272
02273 switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin,
02274 scan->rs_cbuf))
02275 {
02276 case HEAPTUPLE_DEAD:
02277
02278 indexIt = false;
02279 tupleIsAlive = false;
02280 break;
02281 case HEAPTUPLE_LIVE:
02282
02283 indexIt = true;
02284 tupleIsAlive = true;
02285 break;
02286 case HEAPTUPLE_RECENTLY_DEAD:
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299 if (HeapTupleIsHotUpdated(heapTuple))
02300 {
02301 indexIt = false;
02302
02303 indexInfo->ii_BrokenHotChain = true;
02304 }
02305 else
02306 indexIt = true;
02307
02308 tupleIsAlive = false;
02309 break;
02310 case HEAPTUPLE_INSERT_IN_PROGRESS:
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320 xwait = HeapTupleHeaderGetXmin(heapTuple->t_data);
02321 if (!TransactionIdIsCurrentTransactionId(xwait))
02322 {
02323 if (!is_system_catalog)
02324 elog(WARNING, "concurrent insert in progress within table \"%s\"",
02325 RelationGetRelationName(heapRelation));
02326
02327
02328
02329
02330
02331
02332
02333 if (checking_uniqueness)
02334 {
02335
02336
02337
02338 LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
02339 XactLockTableWait(xwait);
02340 goto recheck;
02341 }
02342 }
02343
02344
02345
02346
02347
02348 indexIt = true;
02349 tupleIsAlive = true;
02350 break;
02351 case HEAPTUPLE_DELETE_IN_PROGRESS:
02352
02353
02354
02355
02356
02357 xwait = HeapTupleHeaderGetUpdateXid(heapTuple->t_data);
02358 if (!TransactionIdIsCurrentTransactionId(xwait))
02359 {
02360 if (!is_system_catalog)
02361 elog(WARNING, "concurrent delete in progress within table \"%s\"",
02362 RelationGetRelationName(heapRelation));
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378 if (checking_uniqueness ||
02379 HeapTupleIsHotUpdated(heapTuple))
02380 {
02381
02382
02383
02384 LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
02385 XactLockTableWait(xwait);
02386 goto recheck;
02387 }
02388
02389
02390
02391
02392
02393 indexIt = true;
02394 }
02395 else if (HeapTupleIsHotUpdated(heapTuple))
02396 {
02397
02398
02399
02400
02401
02402
02403 indexIt = false;
02404
02405 indexInfo->ii_BrokenHotChain = true;
02406 }
02407 else
02408 {
02409
02410
02411
02412
02413
02414 indexIt = true;
02415 }
02416
02417 tupleIsAlive = false;
02418 break;
02419 default:
02420 elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
02421 indexIt = tupleIsAlive = false;
02422 break;
02423 }
02424
02425 LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
02426
02427 if (!indexIt)
02428 continue;
02429 }
02430 else
02431 {
02432
02433 tupleIsAlive = true;
02434 }
02435
02436 reltuples += 1;
02437
02438 MemoryContextReset(econtext->ecxt_per_tuple_memory);
02439
02440
02441 ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
02442
02443
02444
02445
02446
02447 if (predicate != NIL)
02448 {
02449 if (!ExecQual(predicate, econtext, false))
02450 continue;
02451 }
02452
02453
02454
02455
02456
02457
02458 FormIndexDatum(indexInfo,
02459 slot,
02460 estate,
02461 values,
02462 isnull);
02463
02464
02465
02466
02467
02468
02469
02470 if (HeapTupleIsHeapOnly(heapTuple))
02471 {
02472
02473
02474
02475
02476 HeapTupleData rootTuple;
02477 OffsetNumber offnum;
02478
02479 rootTuple = *heapTuple;
02480 offnum = ItemPointerGetOffsetNumber(&heapTuple->t_self);
02481
02482 Assert(OffsetNumberIsValid(root_offsets[offnum - 1]));
02483
02484 ItemPointerSetOffsetNumber(&rootTuple.t_self,
02485 root_offsets[offnum - 1]);
02486
02487
02488 callback(indexRelation, &rootTuple, values, isnull, tupleIsAlive,
02489 callback_state);
02490 }
02491 else
02492 {
02493
02494 callback(indexRelation, heapTuple, values, isnull, tupleIsAlive,
02495 callback_state);
02496 }
02497 }
02498
02499 heap_endscan(scan);
02500
02501
02502 if (indexInfo->ii_Concurrent)
02503 UnregisterSnapshot(snapshot);
02504
02505 ExecDropSingleTupleTableSlot(slot);
02506
02507 FreeExecutorState(estate);
02508
02509
02510 indexInfo->ii_ExpressionsState = NIL;
02511 indexInfo->ii_PredicateState = NIL;
02512
02513 return reltuples;
02514 }
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529 static void
02530 IndexCheckExclusion(Relation heapRelation,
02531 Relation indexRelation,
02532 IndexInfo *indexInfo)
02533 {
02534 HeapScanDesc scan;
02535 HeapTuple heapTuple;
02536 Datum values[INDEX_MAX_KEYS];
02537 bool isnull[INDEX_MAX_KEYS];
02538 List *predicate;
02539 TupleTableSlot *slot;
02540 EState *estate;
02541 ExprContext *econtext;
02542
02543
02544
02545
02546
02547
02548 if (ReindexIsCurrentlyProcessingIndex(RelationGetRelid(indexRelation)))
02549 ResetReindexProcessing();
02550
02551
02552
02553
02554
02555 estate = CreateExecutorState();
02556 econtext = GetPerTupleExprContext(estate);
02557 slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
02558
02559
02560 econtext->ecxt_scantuple = slot;
02561
02562
02563 predicate = (List *)
02564 ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
02565 estate);
02566
02567
02568
02569
02570 scan = heap_beginscan_strat(heapRelation,
02571 SnapshotNow,
02572 0,
02573 NULL,
02574 true,
02575 true);
02576
02577 while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
02578 {
02579 CHECK_FOR_INTERRUPTS();
02580
02581 MemoryContextReset(econtext->ecxt_per_tuple_memory);
02582
02583
02584 ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
02585
02586
02587
02588
02589 if (predicate != NIL)
02590 {
02591 if (!ExecQual(predicate, econtext, false))
02592 continue;
02593 }
02594
02595
02596
02597
02598 FormIndexDatum(indexInfo,
02599 slot,
02600 estate,
02601 values,
02602 isnull);
02603
02604
02605
02606
02607 check_exclusion_constraint(heapRelation,
02608 indexRelation, indexInfo,
02609 &(heapTuple->t_self), values, isnull,
02610 estate, true, false);
02611 }
02612
02613 heap_endscan(scan);
02614
02615 ExecDropSingleTupleTableSlot(slot);
02616
02617 FreeExecutorState(estate);
02618
02619
02620 indexInfo->ii_ExpressionsState = NIL;
02621 indexInfo->ii_PredicateState = NIL;
02622 }
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688 void
02689 validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
02690 {
02691 Relation heapRelation,
02692 indexRelation;
02693 IndexInfo *indexInfo;
02694 IndexVacuumInfo ivinfo;
02695 v_i_state state;
02696 Oid save_userid;
02697 int save_sec_context;
02698 int save_nestlevel;
02699
02700
02701 heapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
02702
02703 indexRelation = index_open(indexId, RowExclusiveLock);
02704
02705
02706
02707
02708
02709
02710 indexInfo = BuildIndexInfo(indexRelation);
02711
02712
02713 indexInfo->ii_Concurrent = true;
02714
02715
02716
02717
02718
02719
02720 GetUserIdAndSecContext(&save_userid, &save_sec_context);
02721 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
02722 save_sec_context | SECURITY_RESTRICTED_OPERATION);
02723 save_nestlevel = NewGUCNestLevel();
02724
02725
02726
02727
02728 ivinfo.index = indexRelation;
02729 ivinfo.analyze_only = false;
02730 ivinfo.estimated_count = true;
02731 ivinfo.message_level = DEBUG2;
02732 ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
02733 ivinfo.strategy = NULL;
02734
02735 state.tuplesort = tuplesort_begin_datum(TIDOID, TIDLessOperator,
02736 InvalidOid, false,
02737 maintenance_work_mem,
02738 false);
02739 state.htups = state.itups = state.tups_inserted = 0;
02740
02741 (void) index_bulk_delete(&ivinfo, NULL,
02742 validate_index_callback, (void *) &state);
02743
02744
02745 tuplesort_performsort(state.tuplesort);
02746
02747
02748
02749
02750 validate_index_heapscan(heapRelation,
02751 indexRelation,
02752 indexInfo,
02753 snapshot,
02754 &state);
02755
02756
02757 tuplesort_end(state.tuplesort);
02758
02759 elog(DEBUG2,
02760 "validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
02761 state.htups, state.itups, state.tups_inserted);
02762
02763
02764 AtEOXact_GUC(false, save_nestlevel);
02765
02766
02767 SetUserIdAndSecContext(save_userid, save_sec_context);
02768
02769
02770 index_close(indexRelation, NoLock);
02771 heap_close(heapRelation, NoLock);
02772 }
02773
02774
02775
02776
02777 static bool
02778 validate_index_callback(ItemPointer itemptr, void *opaque)
02779 {
02780 v_i_state *state = (v_i_state *) opaque;
02781
02782 tuplesort_putdatum(state->tuplesort, PointerGetDatum(itemptr), false);
02783 state->itups += 1;
02784 return false;
02785 }
02786
02787
02788
02789
02790
02791
02792
02793 static void
02794 validate_index_heapscan(Relation heapRelation,
02795 Relation indexRelation,
02796 IndexInfo *indexInfo,
02797 Snapshot snapshot,
02798 v_i_state *state)
02799 {
02800 HeapScanDesc scan;
02801 HeapTuple heapTuple;
02802 Datum values[INDEX_MAX_KEYS];
02803 bool isnull[INDEX_MAX_KEYS];
02804 List *predicate;
02805 TupleTableSlot *slot;
02806 EState *estate;
02807 ExprContext *econtext;
02808 BlockNumber root_blkno = InvalidBlockNumber;
02809 OffsetNumber root_offsets[MaxHeapTuplesPerPage];
02810 bool in_index[MaxHeapTuplesPerPage];
02811
02812
02813 ItemPointer indexcursor = NULL;
02814 bool tuplesort_empty = false;
02815
02816
02817
02818
02819 Assert(OidIsValid(indexRelation->rd_rel->relam));
02820
02821
02822
02823
02824
02825 estate = CreateExecutorState();
02826 econtext = GetPerTupleExprContext(estate);
02827 slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
02828
02829
02830 econtext->ecxt_scantuple = slot;
02831
02832
02833 predicate = (List *)
02834 ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
02835 estate);
02836
02837
02838
02839
02840
02841
02842
02843 scan = heap_beginscan_strat(heapRelation,
02844 snapshot,
02845 0,
02846 NULL,
02847 true,
02848 false);
02849
02850
02851
02852
02853 while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
02854 {
02855 ItemPointer heapcursor = &heapTuple->t_self;
02856 ItemPointerData rootTuple;
02857 OffsetNumber root_offnum;
02858
02859 CHECK_FOR_INTERRUPTS();
02860
02861 state->htups += 1;
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877 if (scan->rs_cblock != root_blkno)
02878 {
02879 Page page = BufferGetPage(scan->rs_cbuf);
02880
02881 LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
02882 heap_get_root_tuples(page, root_offsets);
02883 LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
02884
02885 memset(in_index, 0, sizeof(in_index));
02886
02887 root_blkno = scan->rs_cblock;
02888 }
02889
02890
02891 rootTuple = *heapcursor;
02892 root_offnum = ItemPointerGetOffsetNumber(heapcursor);
02893
02894 if (HeapTupleIsHeapOnly(heapTuple))
02895 {
02896 root_offnum = root_offsets[root_offnum - 1];
02897 Assert(OffsetNumberIsValid(root_offnum));
02898 ItemPointerSetOffsetNumber(&rootTuple, root_offnum);
02899 }
02900
02901
02902
02903
02904
02905 while (!tuplesort_empty &&
02906 (!indexcursor ||
02907 ItemPointerCompare(indexcursor, &rootTuple) < 0))
02908 {
02909 Datum ts_val;
02910 bool ts_isnull;
02911
02912 if (indexcursor)
02913 {
02914
02915
02916
02917 if (ItemPointerGetBlockNumber(indexcursor) == root_blkno)
02918 in_index[ItemPointerGetOffsetNumber(indexcursor) - 1] = true;
02919 pfree(indexcursor);
02920 }
02921
02922 tuplesort_empty = !tuplesort_getdatum(state->tuplesort, true,
02923 &ts_val, &ts_isnull);
02924 Assert(tuplesort_empty || !ts_isnull);
02925 indexcursor = (ItemPointer) DatumGetPointer(ts_val);
02926 }
02927
02928
02929
02930
02931
02932 if ((tuplesort_empty ||
02933 ItemPointerCompare(indexcursor, &rootTuple) > 0) &&
02934 !in_index[root_offnum - 1])
02935 {
02936 MemoryContextReset(econtext->ecxt_per_tuple_memory);
02937
02938
02939 ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
02940
02941
02942
02943
02944
02945 if (predicate != NIL)
02946 {
02947 if (!ExecQual(predicate, econtext, false))
02948 continue;
02949 }
02950
02951
02952
02953
02954
02955
02956 FormIndexDatum(indexInfo,
02957 slot,
02958 estate,
02959 values,
02960 isnull);
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980 index_insert(indexRelation,
02981 values,
02982 isnull,
02983 &rootTuple,
02984 heapRelation,
02985 indexInfo->ii_Unique ?
02986 UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
02987
02988 state->tups_inserted += 1;
02989 }
02990 }
02991
02992 heap_endscan(scan);
02993
02994 ExecDropSingleTupleTableSlot(slot);
02995
02996 FreeExecutorState(estate);
02997
02998
02999 indexInfo->ii_ExpressionsState = NIL;
03000 indexInfo->ii_PredicateState = NIL;
03001 }
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020 void
03021 index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
03022 {
03023 Relation pg_index;
03024 HeapTuple indexTuple;
03025 Form_pg_index indexForm;
03026
03027
03028 Assert(GetTopTransactionIdIfAny() == InvalidTransactionId);
03029
03030
03031 pg_index = heap_open(IndexRelationId, RowExclusiveLock);
03032
03033 indexTuple = SearchSysCacheCopy1(INDEXRELID,
03034 ObjectIdGetDatum(indexId));
03035 if (!HeapTupleIsValid(indexTuple))
03036 elog(ERROR, "cache lookup failed for index %u", indexId);
03037 indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
03038
03039
03040 switch (action)
03041 {
03042 case INDEX_CREATE_SET_READY:
03043
03044 Assert(indexForm->indislive);
03045 Assert(!indexForm->indisready);
03046 Assert(!indexForm->indisvalid);
03047 indexForm->indisready = true;
03048 break;
03049 case INDEX_CREATE_SET_VALID:
03050
03051 Assert(indexForm->indislive);
03052 Assert(indexForm->indisready);
03053 Assert(!indexForm->indisvalid);
03054 indexForm->indisvalid = true;
03055 break;
03056 case INDEX_DROP_CLEAR_VALID:
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070 indexForm->indisvalid = false;
03071 indexForm->indisclustered = false;
03072 break;
03073 case INDEX_DROP_SET_DEAD:
03074
03075
03076
03077
03078
03079
03080
03081
03082 Assert(!indexForm->indisvalid);
03083 indexForm->indisready = false;
03084 indexForm->indislive = false;
03085 break;
03086 }
03087
03088
03089 heap_inplace_update(pg_index, indexTuple);
03090
03091 heap_close(pg_index, RowExclusiveLock);
03092 }
03093
03094
03095
03096
03097
03098
03099 Oid
03100 IndexGetRelation(Oid indexId, bool missing_ok)
03101 {
03102 HeapTuple tuple;
03103 Form_pg_index index;
03104 Oid result;
03105
03106 tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
03107 if (!HeapTupleIsValid(tuple))
03108 {
03109 if (missing_ok)
03110 return InvalidOid;
03111 elog(ERROR, "cache lookup failed for index %u", indexId);
03112 }
03113 index = (Form_pg_index) GETSTRUCT(tuple);
03114 Assert(index->indexrelid == indexId);
03115
03116 result = index->indrelid;
03117 ReleaseSysCache(tuple);
03118 return result;
03119 }
03120
03121
03122
03123
03124 void
03125 reindex_index(Oid indexId, bool skip_constraint_checks)
03126 {
03127 Relation iRel,
03128 heapRelation;
03129 Oid heapId;
03130 IndexInfo *indexInfo;
03131 volatile bool skipped_constraint = false;
03132
03133
03134
03135
03136
03137 heapId = IndexGetRelation(indexId, false);
03138 heapRelation = heap_open(heapId, ShareLock);
03139
03140
03141
03142
03143
03144 iRel = index_open(indexId, AccessExclusiveLock);
03145
03146
03147
03148
03149
03150 if (RELATION_IS_OTHER_TEMP(iRel))
03151 ereport(ERROR,
03152 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03153 errmsg("cannot reindex temporary tables of other sessions")));
03154
03155
03156
03157
03158
03159 CheckTableNotInUse(iRel, "REINDEX INDEX");
03160
03161
03162
03163
03164
03165 TransferPredicateLocksToHeapRelation(iRel);
03166
03167 PG_TRY();
03168 {
03169
03170 SetReindexProcessing(heapId, indexId);
03171
03172
03173 indexInfo = BuildIndexInfo(iRel);
03174
03175
03176 if (skip_constraint_checks)
03177 {
03178 if (indexInfo->ii_Unique || indexInfo->ii_ExclusionOps != NULL)
03179 skipped_constraint = true;
03180 indexInfo->ii_Unique = false;
03181 indexInfo->ii_ExclusionOps = NULL;
03182 indexInfo->ii_ExclusionProcs = NULL;
03183 indexInfo->ii_ExclusionStrats = NULL;
03184 }
03185
03186
03187 RelationSetNewRelfilenode(iRel, InvalidTransactionId,
03188 InvalidMultiXactId);
03189
03190
03191
03192 index_build(heapRelation, iRel, indexInfo, false, true);
03193 }
03194 PG_CATCH();
03195 {
03196
03197 ResetReindexProcessing();
03198 PG_RE_THROW();
03199 }
03200 PG_END_TRY();
03201 ResetReindexProcessing();
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239 if (!skipped_constraint)
03240 {
03241 Relation pg_index;
03242 HeapTuple indexTuple;
03243 Form_pg_index indexForm;
03244 bool index_bad;
03245
03246 pg_index = heap_open(IndexRelationId, RowExclusiveLock);
03247
03248 indexTuple = SearchSysCacheCopy1(INDEXRELID,
03249 ObjectIdGetDatum(indexId));
03250 if (!HeapTupleIsValid(indexTuple))
03251 elog(ERROR, "cache lookup failed for index %u", indexId);
03252 indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
03253
03254 index_bad = (!indexForm->indisvalid ||
03255 !indexForm->indisready ||
03256 !indexForm->indislive);
03257 if (index_bad ||
03258 (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain))
03259 {
03260 if (!indexInfo->ii_BrokenHotChain)
03261 indexForm->indcheckxmin = false;
03262 else if (index_bad)
03263 indexForm->indcheckxmin = true;
03264 indexForm->indisvalid = true;
03265 indexForm->indisready = true;
03266 indexForm->indislive = true;
03267 simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
03268 CatalogUpdateIndexes(pg_index, indexTuple);
03269
03270
03271
03272
03273
03274
03275
03276
03277 CacheInvalidateRelcache(heapRelation);
03278 }
03279
03280 heap_close(pg_index, RowExclusiveLock);
03281 }
03282
03283
03284 index_close(iRel, NoLock);
03285 heap_close(heapRelation, NoLock);
03286 }
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317 bool
03318 reindex_relation(Oid relid, int flags)
03319 {
03320 Relation rel;
03321 Oid toast_relid;
03322 List *indexIds;
03323 bool is_pg_class;
03324 bool result;
03325
03326
03327
03328
03329
03330
03331 rel = heap_open(relid, ShareLock);
03332
03333 toast_relid = rel->rd_rel->reltoastrelid;
03334
03335
03336
03337
03338
03339
03340 indexIds = RelationGetIndexList(rel);
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364 is_pg_class = (RelationGetRelid(rel) == RelationRelationId);
03365
03366
03367 if (is_pg_class)
03368 (void) RelationGetIndexAttrBitmap(rel, false);
03369
03370 PG_TRY();
03371 {
03372 List *doneIndexes;
03373 ListCell *indexId;
03374
03375 if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
03376 {
03377
03378 SetReindexPending(indexIds);
03379
03380
03381
03382
03383
03384 CommandCounterIncrement();
03385 }
03386
03387
03388 doneIndexes = NIL;
03389 foreach(indexId, indexIds)
03390 {
03391 Oid indexOid = lfirst_oid(indexId);
03392
03393 if (is_pg_class)
03394 RelationSetIndexList(rel, doneIndexes, InvalidOid);
03395
03396 reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS));
03397
03398 CommandCounterIncrement();
03399
03400
03401 Assert(!ReindexIsProcessingIndex(indexOid));
03402
03403 if (is_pg_class)
03404 doneIndexes = lappend_oid(doneIndexes, indexOid);
03405 }
03406 }
03407 PG_CATCH();
03408 {
03409
03410 ResetReindexPending();
03411 PG_RE_THROW();
03412 }
03413 PG_END_TRY();
03414 ResetReindexPending();
03415
03416 if (is_pg_class)
03417 RelationSetIndexList(rel, indexIds, ClassOidIndexId);
03418
03419
03420
03421
03422 heap_close(rel, NoLock);
03423
03424 result = (indexIds != NIL);
03425
03426
03427
03428
03429
03430 if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid))
03431 result |= reindex_relation(toast_relid, flags);
03432
03433 return result;
03434 }
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447 static Oid currentlyReindexedHeap = InvalidOid;
03448 static Oid currentlyReindexedIndex = InvalidOid;
03449 static List *pendingReindexedIndexes = NIL;
03450
03451
03452
03453
03454
03455 bool
03456 ReindexIsProcessingHeap(Oid heapOid)
03457 {
03458 return heapOid == currentlyReindexedHeap;
03459 }
03460
03461
03462
03463
03464
03465 static bool
03466 ReindexIsCurrentlyProcessingIndex(Oid indexOid)
03467 {
03468 return indexOid == currentlyReindexedIndex;
03469 }
03470
03471
03472
03473
03474
03475
03476 bool
03477 ReindexIsProcessingIndex(Oid indexOid)
03478 {
03479 return indexOid == currentlyReindexedIndex ||
03480 list_member_oid(pendingReindexedIndexes, indexOid);
03481 }
03482
03483
03484
03485
03486
03487
03488
03489 static void
03490 SetReindexProcessing(Oid heapOid, Oid indexOid)
03491 {
03492 Assert(OidIsValid(heapOid) && OidIsValid(indexOid));
03493
03494 if (OidIsValid(currentlyReindexedHeap))
03495 elog(ERROR, "cannot reindex while reindexing");
03496 currentlyReindexedHeap = heapOid;
03497 currentlyReindexedIndex = indexOid;
03498
03499 RemoveReindexPending(indexOid);
03500 }
03501
03502
03503
03504
03505
03506 static void
03507 ResetReindexProcessing(void)
03508 {
03509 currentlyReindexedHeap = InvalidOid;
03510 currentlyReindexedIndex = InvalidOid;
03511 }
03512
03513
03514
03515
03516
03517
03518
03519
03520 static void
03521 SetReindexPending(List *indexes)
03522 {
03523
03524 if (pendingReindexedIndexes)
03525 elog(ERROR, "cannot reindex while reindexing");
03526 pendingReindexedIndexes = list_copy(indexes);
03527 }
03528
03529
03530
03531
03532
03533 static void
03534 RemoveReindexPending(Oid indexOid)
03535 {
03536 pendingReindexedIndexes = list_delete_oid(pendingReindexedIndexes,
03537 indexOid);
03538 }
03539
03540
03541
03542
03543
03544 static void
03545 ResetReindexPending(void)
03546 {
03547 pendingReindexedIndexes = NIL;
03548 }