OSDN Git Service

This patch wraps all accesses to t_xmin, t_cmin, t_xmax, and t_cmax in
[pg-rex/syncrep.git] / src / backend / catalog / index.c
1 /*-------------------------------------------------------------------------
2  *
3  * index.c
4  *        code to create and destroy POSTGRES index relations
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.180 2002/06/15 19:54:23 momjian Exp $
12  *
13  *
14  * INTERFACE ROUTINES
15  *              index_create()                  - Create a cataloged index relation
16  *              index_drop()                    - Removes index relation from catalogs
17  *              BuildIndexInfo()                - Prepare to insert index tuples
18  *              FormIndexDatum()                - Construct datum vector for one index tuple
19  *
20  *-------------------------------------------------------------------------
21  */
22 #include "postgres.h"
23
24 #include <unistd.h>
25
26 #include "access/genam.h"
27 #include "access/heapam.h"
28 #include "access/istrat.h"
29 #include "bootstrap/bootstrap.h"
30 #include "catalog/catalog.h"
31 #include "catalog/catname.h"
32 #include "catalog/heap.h"
33 #include "catalog/index.h"
34 #include "catalog/indexing.h"
35 #include "catalog/pg_index.h"
36 #include "catalog/pg_opclass.h"
37 #include "catalog/pg_proc.h"
38 #include "catalog/pg_type.h"
39 #include "commands/comment.h"
40 #include "executor/executor.h"
41 #include "miscadmin.h"
42 #include "optimizer/clauses.h"
43 #include "optimizer/prep.h"
44 #include "parser/parse_func.h"
45 #include "storage/sinval.h"
46 #include "storage/smgr.h"
47 #include "utils/builtins.h"
48 #include "utils/catcache.h"
49 #include "utils/fmgroids.h"
50 #include "utils/inval.h"
51 #include "utils/lsyscache.h"
52 #include "utils/relcache.h"
53 #include "utils/syscache.h"
54
55
56 /*
57  * macros used in guessing how many tuples are on a page.
58  */
59 #define AVG_ATTR_SIZE 8
60 #define NTUPLES_PER_PAGE(natts) \
61         ((BLCKSZ - MAXALIGN(sizeof(PageHeaderData))) / \
62         ((natts) * AVG_ATTR_SIZE + MAXALIGN(sizeof(HeapTupleHeaderData))))
63
64 /* non-export function prototypes */
65 static TupleDesc BuildFuncTupleDesc(Oid funcOid,
66                                    Oid *classObjectId);
67 static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
68                                                  int numatts, AttrNumber *attNums,
69                                                  Oid *classObjectId);
70 static void UpdateRelationRelation(Relation indexRelation);
71 static void InitializeAttributeOids(Relation indexRelation,
72                                                 int numatts, Oid indexoid);
73 static void AppendAttributeTuples(Relation indexRelation, int numatts);
74 static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
75                                         IndexInfo *indexInfo,
76                                         Oid *classOids,
77                                         bool primary);
78 static Oid      IndexGetRelation(Oid indexId);
79 static bool activate_index(Oid indexId, bool activate, bool inplace);
80
81
82 static bool reindexing = false;
83
84
85 bool
86 SetReindexProcessing(bool reindexmode)
87 {
88         bool            old = reindexing;
89
90         reindexing = reindexmode;
91         return old;
92 }
93
94 bool
95 IsReindexProcessing(void)
96 {
97         return reindexing;
98 }
99
100 static TupleDesc
101 BuildFuncTupleDesc(Oid funcOid,
102                                    Oid *classObjectId)
103 {
104         TupleDesc       funcTupDesc;
105         HeapTuple       tuple;
106         Oid                     keyType;
107         Oid                     retType;
108         Form_pg_type typeTup;
109
110         /*
111          * Allocate and zero a tuple descriptor for a one-column tuple.
112          */
113         funcTupDesc = CreateTemplateTupleDesc(1);
114         funcTupDesc->attrs[0] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
115         MemSet(funcTupDesc->attrs[0], 0, ATTRIBUTE_TUPLE_SIZE);
116
117         /*
118          * Lookup the function to get its name and return type.
119          */
120         tuple = SearchSysCache(PROCOID,
121                                                    ObjectIdGetDatum(funcOid),
122                                                    0, 0, 0);
123         if (!HeapTupleIsValid(tuple))
124                 elog(ERROR, "Function %u does not exist", funcOid);
125         retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
126
127         /*
128          * make the attributes name the same as the functions
129          */
130         namestrcpy(&funcTupDesc->attrs[0]->attname,
131                            NameStr(((Form_pg_proc) GETSTRUCT(tuple))->proname));
132
133         ReleaseSysCache(tuple);
134
135         /*
136          * Check the opclass to see if it provides a keytype (overriding the
137          * function result type).
138          */
139         tuple = SearchSysCache(CLAOID,
140                                                    ObjectIdGetDatum(classObjectId[0]),
141                                                    0, 0, 0);
142         if (!HeapTupleIsValid(tuple))
143                 elog(ERROR, "Opclass %u does not exist", classObjectId[0]);
144         keyType = ((Form_pg_opclass) GETSTRUCT(tuple))->opckeytype;
145         ReleaseSysCache(tuple);
146
147         if (!OidIsValid(keyType))
148                 keyType = retType;
149
150         /*
151          * Lookup the key type in pg_type for the type length etc.
152          */
153         tuple = SearchSysCache(TYPEOID,
154                                                    ObjectIdGetDatum(keyType),
155                                                    0, 0, 0);
156         if (!HeapTupleIsValid(tuple))
157                 elog(ERROR, "Type %u does not exist", keyType);
158         typeTup = (Form_pg_type) GETSTRUCT(tuple);
159
160         /*
161          * Assign some of the attributes values. Leave the rest as 0.
162          */
163         funcTupDesc->attrs[0]->attnum = 1;
164         funcTupDesc->attrs[0]->atttypid = keyType;
165         funcTupDesc->attrs[0]->attlen = typeTup->typlen;
166         funcTupDesc->attrs[0]->attbyval = typeTup->typbyval;
167         funcTupDesc->attrs[0]->attcacheoff = -1;
168         funcTupDesc->attrs[0]->atttypmod = -1;
169         funcTupDesc->attrs[0]->attstorage = typeTup->typstorage;
170         funcTupDesc->attrs[0]->attalign = typeTup->typalign;
171
172         ReleaseSysCache(tuple);
173
174         return funcTupDesc;
175 }
176
177 /* ----------------------------------------------------------------
178  *              ConstructTupleDescriptor
179  *
180  * Build an index tuple descriptor for a new index (plain not functional)
181  * ----------------------------------------------------------------
182  */
183 static TupleDesc
184 ConstructTupleDescriptor(Relation heapRelation,
185                                                  int numatts,
186                                                  AttrNumber *attNums,
187                                                  Oid *classObjectId)
188 {
189         TupleDesc       heapTupDesc;
190         TupleDesc       indexTupDesc;
191         int                     natts;                  /* #atts in heap rel --- for error checks */
192         int                     i;
193
194         heapTupDesc = RelationGetDescr(heapRelation);
195         natts = RelationGetForm(heapRelation)->relnatts;
196
197         /*
198          * allocate the new tuple descriptor
199          */
200
201         indexTupDesc = CreateTemplateTupleDesc(numatts);
202
203         /* ----------------
204          *        for each attribute we are indexing, obtain its attribute
205          *        tuple form from either the static table of system attribute
206          *        tuple forms or the relation tuple descriptor
207          * ----------------
208          */
209         for (i = 0; i < numatts; i++)
210         {
211                 AttrNumber      atnum;          /* attributeNumber[attributeOffset] */
212                 Form_pg_attribute from;
213                 Form_pg_attribute to;
214                 HeapTuple       tuple;
215                 Oid                     keyType;
216
217                 /*
218                  * get the attribute number and make sure it's valid; determine
219                  * which attribute descriptor to copy
220                  */
221                 atnum = attNums[i];
222
223                 if (!AttrNumberIsForUserDefinedAttr(atnum))
224                 {
225                         /*
226                          * here we are indexing on a system attribute (-1...-n)
227                          */
228                         from = SystemAttributeDefinition(atnum,
229                                                                            heapRelation->rd_rel->relhasoids);
230                 }
231                 else
232                 {
233                         /*
234                          * here we are indexing on a normal attribute (1...n)
235                          */
236                         if (atnum > natts)
237                                 elog(ERROR, "cannot create index: column %d does not exist",
238                                          atnum);
239
240                         from = heapTupDesc->attrs[AttrNumberGetAttrOffset(atnum)];
241                 }
242
243                 /*
244                  * now that we've determined the "from", let's copy the tuple desc
245                  * data...
246                  */
247                 indexTupDesc->attrs[i] = to =
248                         (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
249                 memcpy(to, from, ATTRIBUTE_TUPLE_SIZE);
250
251                 /*
252                  * Fix the stuff that should not be the same as the underlying
253                  * attr
254                  */
255                 to->attnum = i + 1;
256
257                 to->attstattarget = 0;
258                 to->attcacheoff = -1;
259                 to->attnotnull = false;
260                 to->atthasdef = false;
261
262                 /*
263                  * We do not yet have the correct relation OID for the index, so
264                  * just set it invalid for now.  InitializeAttributeOids() will
265                  * fix it later.
266                  */
267                 to->attrelid = InvalidOid;
268
269                 /*
270                  * Check the opclass to see if it provides a keytype (overriding
271                  * the attribute type).
272                  */
273                 tuple = SearchSysCache(CLAOID,
274                                                            ObjectIdGetDatum(classObjectId[i]),
275                                                            0, 0, 0);
276                 if (!HeapTupleIsValid(tuple))
277                         elog(ERROR, "Opclass %u does not exist", classObjectId[i]);
278                 keyType = ((Form_pg_opclass) GETSTRUCT(tuple))->opckeytype;
279                 ReleaseSysCache(tuple);
280
281                 if (OidIsValid(keyType) && keyType != to->atttypid)
282                 {
283                         /* index value and heap value have different types */
284                         Form_pg_type typeTup;
285
286                         tuple = SearchSysCache(TYPEOID,
287                                                                    ObjectIdGetDatum(keyType),
288                                                                    0, 0, 0);
289                         if (!HeapTupleIsValid(tuple))
290                                 elog(ERROR, "Type %u does not exist", keyType);
291                         typeTup = (Form_pg_type) GETSTRUCT(tuple);
292
293                         to->atttypid = keyType;
294                         to->atttypmod = -1;
295                         to->attlen = typeTup->typlen;
296                         to->attbyval = typeTup->typbyval;
297                         to->attalign = typeTup->typalign;
298                         to->attstorage = typeTup->typstorage;
299
300                         ReleaseSysCache(tuple);
301                 }
302         }
303
304         return indexTupDesc;
305 }
306
307 /* ----------------------------------------------------------------
308  *              UpdateRelationRelation
309  * ----------------------------------------------------------------
310  */
311 static void
312 UpdateRelationRelation(Relation indexRelation)
313 {
314         Relation        pg_class;
315         HeapTuple       tuple;
316         Relation        idescs[Num_pg_class_indices];
317
318         pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
319
320         /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
321         tuple = heap_addheader(Natts_pg_class_fixed,
322                                                    CLASS_TUPLE_SIZE,
323                                                    (void *) indexRelation->rd_rel);
324
325         /*
326          * the new tuple must have the oid already chosen for the index.
327          * sure would be embarrassing to do this sort of thing in polite company.
328          */
329         tuple->t_data->t_oid = RelationGetRelid(indexRelation);
330         simple_heap_insert(pg_class, tuple);
331
332         /*
333          * During normal processing, we need to make sure that the system
334          * catalog indices are correct.  Bootstrap (initdb) time doesn't
335          * require this, because we make sure that the indices are correct
336          * just before exiting.
337          */
338         if (!IsIgnoringSystemIndexes())
339         {
340                 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
341                 CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, tuple);
342                 CatalogCloseIndices(Num_pg_class_indices, idescs);
343         }
344
345         heap_freetuple(tuple);
346         heap_close(pg_class, RowExclusiveLock);
347 }
348
349 /* ----------------------------------------------------------------
350  *              InitializeAttributeOids
351  * ----------------------------------------------------------------
352  */
353 static void
354 InitializeAttributeOids(Relation indexRelation,
355                                                 int numatts,
356                                                 Oid indexoid)
357 {
358         TupleDesc       tupleDescriptor;
359         int                     i;
360
361         tupleDescriptor = RelationGetDescr(indexRelation);
362
363         for (i = 0; i < numatts; i += 1)
364                 tupleDescriptor->attrs[i]->attrelid = indexoid;
365 }
366
367 /* ----------------------------------------------------------------
368  *              AppendAttributeTuples
369  * ----------------------------------------------------------------
370  */
371 static void
372 AppendAttributeTuples(Relation indexRelation, int numatts)
373 {
374         Relation        pg_attribute;
375         bool            hasind;
376         Relation        idescs[Num_pg_attr_indices];
377         TupleDesc       indexTupDesc;
378         HeapTuple       new_tuple;
379         int                     i;
380
381         /*
382          * open the attribute relation
383          */
384         pg_attribute = heap_openr(AttributeRelationName, RowExclusiveLock);
385
386         hasind = false;
387         if (!IsIgnoringSystemIndexes() && pg_attribute->rd_rel->relhasindex)
388         {
389                 hasind = true;
390                 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
391         }
392
393         /*
394          * insert data from new index's tupdesc into pg_attribute
395          */
396         indexTupDesc = RelationGetDescr(indexRelation);
397
398         for (i = 0; i < numatts; i++)
399         {
400                 /*
401                  * There used to be very grotty code here to set these fields, but
402                  * I think it's unnecessary.  They should be set already.
403                  */
404                 Assert(indexTupDesc->attrs[i]->attnum == i + 1);
405                 Assert(indexTupDesc->attrs[i]->attcacheoff == -1);
406
407                 new_tuple = heap_addheader(Natts_pg_attribute,
408                                                                    ATTRIBUTE_TUPLE_SIZE,
409                                                                    (void *) indexTupDesc->attrs[i]);
410
411                 simple_heap_insert(pg_attribute, new_tuple);
412
413                 if (hasind)
414                         CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, new_tuple);
415
416                 heap_freetuple(new_tuple);
417         }
418
419         if (hasind)
420                 CatalogCloseIndices(Num_pg_attr_indices, idescs);
421
422         heap_close(pg_attribute, RowExclusiveLock);
423 }
424
425 /* ----------------------------------------------------------------
426  *              UpdateIndexRelation
427  * ----------------------------------------------------------------
428  */
429 static void
430 UpdateIndexRelation(Oid indexoid,
431                                         Oid heapoid,
432                                         IndexInfo *indexInfo,
433                                         Oid *classOids,
434                                         bool primary)
435 {
436         Form_pg_index indexForm;
437         char       *predString;
438         text       *predText;
439         int                     predLen,
440                                 itupLen;
441         Relation        pg_index;
442         HeapTuple       tuple;
443         int                     i;
444         Relation        idescs[Num_pg_index_indices];
445
446         /*
447          * allocate a Form_pg_index big enough to hold the index-predicate (if
448          * any) in string form
449          */
450         if (indexInfo->ii_Predicate != NIL)
451         {
452                 predString = nodeToString(indexInfo->ii_Predicate);
453                 predText = DatumGetTextP(DirectFunctionCall1(textin,
454                                                                                    CStringGetDatum(predString)));
455                 pfree(predString);
456         }
457         else
458                 predText = DatumGetTextP(DirectFunctionCall1(textin,
459                                                                                                    CStringGetDatum("")));
460
461         predLen = VARSIZE(predText);
462         itupLen = predLen + sizeof(FormData_pg_index);
463         indexForm = (Form_pg_index) palloc(itupLen);
464         MemSet(indexForm, 0, sizeof(FormData_pg_index));
465
466         /*
467          * store information into the index tuple form
468          */
469         indexForm->indexrelid = indexoid;
470         indexForm->indrelid = heapoid;
471         indexForm->indproc = indexInfo->ii_FuncOid;
472         indexForm->indisclustered = false;      /* not used */
473         indexForm->indisunique = indexInfo->ii_Unique;
474         indexForm->indisprimary = primary;
475         memcpy((char *) &indexForm->indpred, (char *) predText, predLen);
476
477         /*
478          * copy index key and op class information
479          *
480          * We zeroed the extra slots (if any) above --- that's essential.
481          */
482         for (i = 0; i < indexInfo->ii_NumKeyAttrs; i++)
483                 indexForm->indkey[i] = indexInfo->ii_KeyAttrNumbers[i];
484
485         for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
486                 indexForm->indclass[i] = classOids[i];
487
488         /*
489          * open the system catalog index relation
490          */
491         pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
492
493         /*
494          * form a tuple to insert into pg_index
495          */
496         tuple = heap_addheader(Natts_pg_index,
497                                                    itupLen,
498                                                    (void *) indexForm);
499
500         /*
501          * insert the tuple into the pg_index
502          */
503         simple_heap_insert(pg_index, tuple);
504
505         /*
506          * add index tuples for it
507          */
508         if (!IsIgnoringSystemIndexes())
509         {
510                 CatalogOpenIndices(Num_pg_index_indices, Name_pg_index_indices, idescs);
511                 CatalogIndexInsert(idescs, Num_pg_index_indices, pg_index, tuple);
512                 CatalogCloseIndices(Num_pg_index_indices, idescs);
513         }
514
515         /*
516          * close the relation and free the tuple
517          */
518         heap_close(pg_index, RowExclusiveLock);
519         pfree(predText);
520         pfree(indexForm);
521         heap_freetuple(tuple);
522 }
523
524
525 /* ----------------------------------------------------------------
526  *              index_create
527  *
528  * Returns OID of the created index.
529  * ----------------------------------------------------------------
530  */
531 Oid
532 index_create(Oid heapRelationId,
533                          const char *indexRelationName,
534                          IndexInfo *indexInfo,
535                          Oid accessMethodObjectId,
536                          Oid *classObjectId,
537                          bool primary,
538                          bool allow_system_table_mods)
539 {
540         Relation        heapRelation;
541         Relation        indexRelation;
542         TupleDesc       indexTupDesc;
543         bool            shared_relation;
544         Oid                     namespaceId;
545         Oid                     indexoid;
546
547         SetReindexProcessing(false);
548
549         /*
550          * Only SELECT ... FOR UPDATE are allowed while doing this
551          */
552         heapRelation = heap_open(heapRelationId, ShareLock);
553
554         /*
555          * The index will be in the same namespace as its parent table,
556          * and is shared across databases if and only if the parent is.
557          */
558         namespaceId = RelationGetNamespace(heapRelation);
559         shared_relation = heapRelation->rd_rel->relisshared;
560
561         /*
562          * check parameters
563          */
564         if (indexInfo->ii_NumIndexAttrs < 1 ||
565                 indexInfo->ii_NumKeyAttrs < 1)
566                 elog(ERROR, "must index at least one column");
567
568         if (!allow_system_table_mods &&
569                 IsSystemRelation(heapRelation) &&
570                 IsNormalProcessingMode())
571                 elog(ERROR, "User-defined indexes on system catalogs are not supported");
572
573         /*
574          * We cannot allow indexing a shared relation after initdb (because
575          * there's no way to make the entry in other databases' pg_class).
576          * Unfortunately we can't distinguish initdb from a manually started
577          * standalone backend.  However, we can at least prevent this mistake
578          * under normal multi-user operation.
579          */
580         if (shared_relation && IsUnderPostmaster)
581                 elog(ERROR, "Shared indexes cannot be created after initdb");
582
583         if (get_relname_relid(indexRelationName, namespaceId))
584                 elog(ERROR, "index named \"%s\" already exists",
585                          indexRelationName);
586
587         /*
588          * construct tuple descriptor for index tuples
589          */
590         if (OidIsValid(indexInfo->ii_FuncOid))
591                 indexTupDesc = BuildFuncTupleDesc(indexInfo->ii_FuncOid,
592                                                                                   classObjectId);
593         else
594                 indexTupDesc = ConstructTupleDescriptor(heapRelation,
595                                                                                                 indexInfo->ii_NumKeyAttrs,
596                                                                                         indexInfo->ii_KeyAttrNumbers,
597                                                                                                 classObjectId);
598
599         /*
600          * create the index relation (but don't create storage yet)
601          */
602         indexRelation = heap_create(indexRelationName,
603                                                                 namespaceId,
604                                                                 indexTupDesc,
605                                                                 shared_relation,
606                                                                 false,
607                                                                 allow_system_table_mods);
608         indexoid = RelationGetRelid(indexRelation);
609
610         /*
611          * Obtain exclusive lock on it.  Although no other backends can see it
612          * until we commit, this prevents deadlock-risk complaints from lock
613          * manager in cases such as CLUSTER.
614          */
615         LockRelation(indexRelation, AccessExclusiveLock);
616
617         /*
618          * Fill in fields of the index's pg_class entry that are not set
619          * correctly by heap_create.
620          *
621          * XXX should have a cleaner way to create cataloged indexes
622          */
623         indexRelation->rd_rel->relowner = GetUserId();
624         indexRelation->rd_rel->relam = accessMethodObjectId;
625         indexRelation->rd_rel->relkind = RELKIND_INDEX;
626         indexRelation->rd_rel->relhasoids = false;
627
628         /*
629          * store index's pg_class entry
630          */
631         UpdateRelationRelation(indexRelation);
632
633         /*
634          * We create the disk file for this relation here
635          */
636         heap_storage_create(indexRelation);
637
638         /*
639          * now update the object id's of all the attribute tuple forms in the
640          * index relation's tuple descriptor
641          */
642         InitializeAttributeOids(indexRelation,
643                                                         indexInfo->ii_NumIndexAttrs,
644                                                         indexoid);
645
646         /*
647          * append ATTRIBUTE tuples for the index
648          */
649         AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs);
650
651         /* ----------------
652          *        update pg_index
653          *        (append INDEX tuple)
654          *
655          *        Note that this stows away a representation of "predicate".
656          *        (Or, could define a rule to maintain the predicate) --Nels, Feb '92
657          * ----------------
658          */
659         UpdateIndexRelation(indexoid, heapRelationId, indexInfo,
660                                                 classObjectId, primary);
661
662         /*
663          * fill in the index strategy structure with information from the
664          * catalogs.  First we must advance the command counter so that we
665          * will see the newly-entered index catalog tuples.
666          */
667         CommandCounterIncrement();
668
669         RelationInitIndexAccessInfo(indexRelation);
670
671         /*
672          * If this is bootstrap (initdb) time, then we don't actually fill in
673          * the index yet.  We'll be creating more indices and classes later,
674          * so we delay filling them in until just before we're done with
675          * bootstrapping.  Otherwise, we call the routine that constructs the
676          * index.
677          *
678          * In normal processing mode, the heap and index relations are closed by
679          * index_build() --- but we continue to hold the ShareLock on the heap
680          * and the exclusive lock on the index that we acquired above, until
681          * end of transaction.
682          */
683         if (IsBootstrapProcessingMode())
684         {
685                 index_register(heapRelationId, indexoid, indexInfo);
686                 /* XXX shouldn't we close the heap and index rels here? */
687         }
688         else
689                 index_build(heapRelation, indexRelation, indexInfo);
690
691         return indexoid;
692 }
693
694 /* ----------------------------------------------------------------
695  *
696  *              index_drop
697  *
698  * ----------------------------------------------------------------
699  */
700 void
701 index_drop(Oid indexId)
702 {
703         Oid                     heapId;
704         Relation        userHeapRelation;
705         Relation        userIndexRelation;
706         Relation        indexRelation;
707         Relation        relationRelation;
708         Relation        attributeRelation;
709         HeapTuple       tuple;
710         int16           attnum;
711         int                     i;
712
713         Assert(OidIsValid(indexId));
714
715         /*
716          * To drop an index safely, we must grab exclusive lock on its parent
717          * table; otherwise there could be other backends using the index!
718          * Exclusive lock on the index alone is insufficient because another
719          * backend might be in the midst of devising a query plan that will
720          * use the index.  The parser and planner take care to hold an
721          * appropriate lock on the parent table while working, but having them
722          * hold locks on all the indexes too seems overly complex.      We do grab
723          * exclusive lock on the index too, just to be safe. Both locks must
724          * be held till end of transaction, else other backends will still see
725          * this index in pg_index.
726          */
727         heapId = IndexGetRelation(indexId);
728         userHeapRelation = heap_open(heapId, AccessExclusiveLock);
729
730         userIndexRelation = index_open(indexId);
731         LockRelation(userIndexRelation, AccessExclusiveLock);
732
733         /*
734          * Note: unlike heap_drop_with_catalog, we do not need to prevent
735          * deletion of system indexes here; that's checked for upstream. If we
736          * did check it here, deletion of TOAST tables would fail...
737          */
738
739         /*
740          * fix DESCRIPTION relation
741          */
742         DeleteComments(indexId, RelOid_pg_class);
743
744         /*
745          * fix RELATION relation
746          */
747         relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
748
749         /* Remove the pg_class tuple for the index itself */
750         tuple = SearchSysCacheCopy(RELOID,
751                                                            ObjectIdGetDatum(indexId),
752                                                            0, 0, 0);
753         if (!HeapTupleIsValid(tuple))
754                 elog(ERROR, "index_drop: cache lookup failed for index %u",
755                          indexId);
756
757         simple_heap_delete(relationRelation, &tuple->t_self);
758         heap_freetuple(tuple);
759
760         heap_close(relationRelation, RowExclusiveLock);
761
762         /*
763          * fix ATTRIBUTE relation
764          */
765         attributeRelation = heap_openr(AttributeRelationName, RowExclusiveLock);
766
767         attnum = 1;                                     /* indexes start at 1 */
768
769         while (HeapTupleIsValid(tuple = SearchSysCacheCopy(ATTNUM,
770                                                                                            ObjectIdGetDatum(indexId),
771                                                                                                    Int16GetDatum(attnum),
772                                                                                                            0, 0)))
773         {
774                 simple_heap_delete(attributeRelation, &tuple->t_self);
775                 heap_freetuple(tuple);
776                 attnum++;
777         }
778         heap_close(attributeRelation, RowExclusiveLock);
779
780         /*
781          * fix INDEX relation
782          */
783         indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
784
785         tuple = SearchSysCacheCopy(INDEXRELID,
786                                                            ObjectIdGetDatum(indexId),
787                                                            0, 0, 0);
788         if (!HeapTupleIsValid(tuple))
789                 elog(ERROR, "index_drop: cache lookup failed for index %u",
790                          indexId);
791
792         simple_heap_delete(indexRelation, &tuple->t_self);
793         heap_freetuple(tuple);
794         heap_close(indexRelation, RowExclusiveLock);
795
796         /*
797          * flush buffer cache and physically remove the file
798          */
799         i = FlushRelationBuffers(userIndexRelation, (BlockNumber) 0);
800         if (i < 0)
801                 elog(ERROR, "index_drop: FlushRelationBuffers returned %d", i);
802
803         smgrunlink(DEFAULT_SMGR, userIndexRelation);
804
805         /*
806          * We are presently too lazy to attempt to compute the new correct value
807          * of relhasindex (the next VACUUM will fix it if necessary).  So there is
808          * no need to update the pg_class tuple for the owning relation.
809          * But we must send out a shared-cache-inval notice on the owning relation
810          * to ensure other backends update their relcache lists of indexes.
811          */
812         CacheInvalidateRelcache(heapId);
813
814         /*
815          * Close rels, but keep locks
816          */
817         index_close(userIndexRelation);
818         heap_close(userHeapRelation, NoLock);
819
820         RelationForgetRelation(indexId);
821 }
822
823 /* ----------------------------------------------------------------
824  *                                              index_build support
825  * ----------------------------------------------------------------
826  */
827
828 /* ----------------
829  *              BuildIndexInfo
830  *                      Construct an IndexInfo record given the index's pg_index tuple
831  *
832  * IndexInfo stores the information about the index that's needed by
833  * FormIndexDatum, which is used for both index_build() and later insertion
834  * of individual index tuples.  Normally we build an IndexInfo for an index
835  * just once per command, and then use it for (potentially) many tuples.
836  * ----------------
837  */
838 IndexInfo *
839 BuildIndexInfo(Form_pg_index indexStruct)
840 {
841         IndexInfo  *ii = makeNode(IndexInfo);
842         int                     i;
843         int                     numKeys;
844
845         /*
846          * count the number of keys, and copy them into the IndexInfo
847          */
848         numKeys = 0;
849         for (i = 0; i < INDEX_MAX_KEYS &&
850                  indexStruct->indkey[i] != InvalidAttrNumber; i++)
851         {
852                 ii->ii_KeyAttrNumbers[i] = indexStruct->indkey[i];
853                 numKeys++;
854         }
855         ii->ii_NumKeyAttrs = numKeys;
856
857         /*
858          * Handle functional index.
859          *
860          * If we have a functional index then the number of attributes defined in
861          * the index must be 1 (the function's single return value). Otherwise
862          * it's same as number of keys.
863          */
864         ii->ii_FuncOid = indexStruct->indproc;
865
866         if (OidIsValid(indexStruct->indproc))
867         {
868                 ii->ii_NumIndexAttrs = 1;
869                 /* Do a lookup on the function, too */
870                 fmgr_info(indexStruct->indproc, &ii->ii_FuncInfo);
871         }
872         else
873                 ii->ii_NumIndexAttrs = numKeys;
874
875         /*
876          * If partial index, convert predicate into expression nodetree
877          */
878         if (VARSIZE(&indexStruct->indpred) > VARHDRSZ)
879         {
880                 char       *predString;
881
882                 predString = DatumGetCString(DirectFunctionCall1(textout,
883                                                                 PointerGetDatum(&indexStruct->indpred)));
884                 ii->ii_Predicate = stringToNode(predString);
885                 pfree(predString);
886         }
887         else
888                 ii->ii_Predicate = NIL;
889
890         /* Other info */
891         ii->ii_Unique = indexStruct->indisunique;
892
893         return ii;
894 }
895
896 /* ----------------
897  *              FormIndexDatum
898  *                      Construct Datum[] and nullv[] arrays for a new index tuple.
899  *
900  *      indexInfo               Info about the index
901  *      heapTuple               Heap tuple for which we must prepare an index entry
902  *      heapDescriptor  tupledesc for heap tuple
903  *      resultCxt               Temporary memory context for any palloc'd datums created
904  *      datum                   Array of index Datums (output area)
905  *      nullv                   Array of is-null indicators (output area)
906  *
907  * For largely historical reasons, we don't actually call index_formtuple()
908  * here, we just prepare its input arrays datum[] and nullv[].
909  * ----------------
910  */
911 void
912 FormIndexDatum(IndexInfo *indexInfo,
913                            HeapTuple heapTuple,
914                            TupleDesc heapDescriptor,
915                            MemoryContext resultCxt,
916                            Datum *datum,
917                            char *nullv)
918 {
919         MemoryContext oldContext;
920         int                     i;
921         Datum           iDatum;
922         bool            isNull;
923
924         oldContext = MemoryContextSwitchTo(resultCxt);
925
926         if (OidIsValid(indexInfo->ii_FuncOid))
927         {
928                 /*
929                  * Functional index --- compute the single index attribute
930                  */
931                 FunctionCallInfoData fcinfo;
932                 bool            anynull = false;
933
934                 MemSet(&fcinfo, 0, sizeof(fcinfo));
935                 fcinfo.flinfo = &indexInfo->ii_FuncInfo;
936                 fcinfo.nargs = indexInfo->ii_NumKeyAttrs;
937
938                 for (i = 0; i < indexInfo->ii_NumKeyAttrs; i++)
939                 {
940                         fcinfo.arg[i] = heap_getattr(heapTuple,
941                                                                                  indexInfo->ii_KeyAttrNumbers[i],
942                                                                                  heapDescriptor,
943                                                                                  &fcinfo.argnull[i]);
944                         anynull |= fcinfo.argnull[i];
945                 }
946                 if (indexInfo->ii_FuncInfo.fn_strict && anynull)
947                 {
948                         /* force a null result for strict function */
949                         iDatum = (Datum) 0;
950                         isNull = true;
951                 }
952                 else
953                 {
954                         iDatum = FunctionCallInvoke(&fcinfo);
955                         isNull = fcinfo.isnull;
956                 }
957                 datum[0] = iDatum;
958                 nullv[0] = (isNull) ? 'n' : ' ';
959         }
960         else
961         {
962                 /*
963                  * Plain index --- for each attribute we need from the heap tuple,
964                  * get the attribute and stick it into the datum and nullv arrays.
965                  */
966                 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
967                 {
968                         iDatum = heap_getattr(heapTuple,
969                                                                   indexInfo->ii_KeyAttrNumbers[i],
970                                                                   heapDescriptor,
971                                                                   &isNull);
972                         datum[i] = iDatum;
973                         nullv[i] = (isNull) ? 'n' : ' ';
974                 }
975         }
976
977         MemoryContextSwitchTo(oldContext);
978 }
979
980
981 /* --------------------------------------------
982  *              Lock class info for update
983  * --------------------------------------------
984  */
985 static bool
986 LockClassinfoForUpdate(Oid relid, HeapTuple rtup,
987                                            Buffer *buffer, bool confirmCommitted)
988 {
989         HeapTuple       classTuple;
990         bool            test;
991         Relation        relationRelation;
992
993         /*
994          * NOTE: get and hold RowExclusiveLock on pg_class, because caller
995          * will probably modify the rel's pg_class tuple later on.
996          */
997         relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
998         classTuple = SearchSysCache(RELOID, PointerGetDatum(relid),
999                                                                 0, 0, 0);
1000         if (!HeapTupleIsValid(classTuple))
1001         {
1002                 heap_close(relationRelation, NoLock);
1003                 return false;
1004         }
1005         rtup->t_self = classTuple->t_self;
1006         ReleaseSysCache(classTuple);
1007
1008         while (1)
1009         {
1010                 ItemPointerData tidsave;
1011
1012                 ItemPointerCopy(&(rtup->t_self), &tidsave);
1013                 test = heap_mark4update(relationRelation, rtup, buffer,
1014                                                                 GetCurrentCommandId());
1015                 switch (test)
1016                 {
1017                         case HeapTupleSelfUpdated:
1018                         case HeapTupleMayBeUpdated:
1019                                 break;
1020                         case HeapTupleUpdated:
1021                                 ReleaseBuffer(*buffer);
1022                                 if (!ItemPointerEquals(&(rtup->t_self), &tidsave))
1023                                         continue;
1024                         default:
1025                                 elog(ERROR, "LockClassinfoForUpdate couldn't lock relid %u", relid);
1026                                 return false;
1027                 }
1028                 break;
1029         }
1030         CacheInvalidateHeapTuple(relationRelation, rtup);
1031         if (confirmCommitted)
1032         {
1033                 HeapTupleHeader th = rtup->t_data;
1034
1035                 if (!(th->t_infomask & HEAP_XMIN_COMMITTED))
1036                         elog(ERROR, "The tuple isn't committed");
1037                 if (th->t_infomask & HEAP_XMAX_COMMITTED)
1038                         if (!(th->t_infomask & HEAP_MARKED_FOR_UPDATE))
1039                                 elog(ERROR, "The tuple is already deleted");
1040         }
1041         heap_close(relationRelation, NoLock);
1042         return true;
1043 }
1044
1045 /* ---------------------------------------------
1046  *              Indexes of the relation active ?
1047  * ---------------------------------------------
1048  */
1049 bool
1050 IndexesAreActive(Oid relid, bool confirmCommitted)
1051 {
1052         HeapTupleData tuple;
1053         Relation        indexRelation;
1054         Buffer          buffer;
1055         HeapScanDesc scan;
1056         ScanKeyData entry;
1057         bool            isactive;
1058
1059         if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted))
1060                 elog(ERROR, "IndexesAreActive couldn't lock %u", relid);
1061         if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION &&
1062           ((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_TOASTVALUE)
1063                 elog(ERROR, "relation %u isn't an indexable relation", relid);
1064         isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex;
1065         ReleaseBuffer(buffer);
1066         if (isactive)
1067                 return isactive;
1068         indexRelation = heap_openr(IndexRelationName, AccessShareLock);
1069         ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
1070                                                    F_OIDEQ, ObjectIdGetDatum(relid));
1071         scan = heap_beginscan(indexRelation, SnapshotNow, 1, &entry);
1072         if (heap_getnext(scan, ForwardScanDirection) == NULL)
1073                 isactive = true;                /* no indexes, so report "active" */
1074         heap_endscan(scan);
1075         heap_close(indexRelation, AccessShareLock);
1076         return isactive;
1077 }
1078
1079 /* ----------------
1080  *              set relhasindex of relation's pg_class entry
1081  *
1082  * If isprimary is TRUE, we are defining a primary index, so also set
1083  * relhaspkey to TRUE.  Otherwise, leave relhaspkey alone.
1084  *
1085  * If reltoastidxid is not InvalidOid, also set reltoastidxid to that value.
1086  * This is only used for TOAST relations.
1087  *
1088  * NOTE: an important side-effect of this operation is that an SI invalidation
1089  * message is sent out to all backends --- including me --- causing relcache
1090  * entries to be flushed or updated with the new hasindex data.  This must
1091  * happen even if we find that no change is needed in the pg_class row.
1092  * ----------------
1093  */
1094 void
1095 setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
1096 {
1097         Relation        pg_class;
1098         HeapTuple       tuple;
1099         Form_pg_class classtuple;
1100         bool            dirty = false;
1101         HeapScanDesc pg_class_scan = NULL;
1102
1103         /*
1104          * Find the tuple to update in pg_class.
1105          */
1106         pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
1107
1108         if (!IsIgnoringSystemIndexes() &&
1109                 (!IsReindexProcessing() || pg_class->rd_rel->relhasindex))
1110         {
1111                 tuple = SearchSysCacheCopy(RELOID,
1112                                                                    ObjectIdGetDatum(relid),
1113                                                                    0, 0, 0);
1114         }
1115         else
1116         {
1117                 ScanKeyData key[1];
1118
1119                 ScanKeyEntryInitialize(&key[0], 0,
1120                                                            ObjectIdAttributeNumber,
1121                                                            F_OIDEQ,
1122                                                            ObjectIdGetDatum(relid));
1123
1124                 pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key);
1125                 tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
1126         }
1127
1128         if (!HeapTupleIsValid(tuple))
1129         {
1130                 if (pg_class_scan)
1131                         heap_endscan(pg_class_scan);
1132                 heap_close(pg_class, RowExclusiveLock);
1133                 elog(ERROR, "setRelhasindex: cannot find relation %u in pg_class",
1134                          relid);
1135         }
1136
1137         /*
1138          * Update fields in the pg_class tuple.
1139          */
1140         if (pg_class_scan)
1141                 LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE);
1142
1143         classtuple = (Form_pg_class) GETSTRUCT(tuple);
1144
1145         if (classtuple->relhasindex != hasindex)
1146         {
1147                 classtuple->relhasindex = hasindex;
1148                 dirty = true;
1149         }
1150         if (isprimary)
1151         {
1152                 if (!classtuple->relhaspkey)
1153                 {
1154                         classtuple->relhaspkey = true;
1155                         dirty = true;
1156                 }
1157         }
1158         if (OidIsValid(reltoastidxid))
1159         {
1160                 Assert(classtuple->relkind == RELKIND_TOASTVALUE);
1161                 if (classtuple->reltoastidxid != reltoastidxid)
1162                 {
1163                         classtuple->reltoastidxid = reltoastidxid;
1164                         dirty = true;
1165                 }
1166         }
1167
1168         if (pg_class_scan)
1169                 LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
1170
1171         if (pg_class_scan)
1172         {
1173                 /* Write the modified tuple in-place */
1174                 WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
1175                 /* Send out shared cache inval if necessary */
1176                 if (!IsBootstrapProcessingMode())
1177                         CacheInvalidateHeapTuple(pg_class, tuple);
1178                 BufferSync();
1179         }
1180         else if (dirty)
1181         {
1182                 simple_heap_update(pg_class, &tuple->t_self, tuple);
1183
1184                 /* Keep the catalog indices up to date */
1185                 if (!IsIgnoringSystemIndexes())
1186                 {
1187                         Relation        idescs[Num_pg_class_indices];
1188
1189                         CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
1190                                                            idescs);
1191                         CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, tuple);
1192                         CatalogCloseIndices(Num_pg_class_indices, idescs);
1193                 }
1194         }
1195         else
1196         {
1197                 /* no need to change tuple, but force relcache rebuild anyway */
1198                 CacheInvalidateRelcache(relid);
1199         }
1200
1201         if (!pg_class_scan)
1202                 heap_freetuple(tuple);
1203         else
1204                 heap_endscan(pg_class_scan);
1205
1206         heap_close(pg_class, RowExclusiveLock);
1207 }
1208
1209 void
1210 setNewRelfilenode(Relation relation)
1211 {
1212         Relation        pg_class,
1213                                 idescs[Num_pg_class_indices];
1214         Oid                     newrelfilenode;
1215         bool            in_place_update = false;
1216         HeapTupleData lockTupleData;
1217         HeapTuple       classTuple = NULL;
1218         Buffer          buffer;
1219         RelationData workrel;
1220
1221         Assert(!IsSystemRelation(relation) || relation->rd_rel->relkind == RELKIND_INDEX);
1222
1223         pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
1224         /* Fetch and lock the classTuple associated with this relation */
1225         if (!LockClassinfoForUpdate(relation->rd_id, &lockTupleData, &buffer, true))
1226                 elog(ERROR, "setNewRelfilenode impossible to lock class tuple");
1227         if (IsIgnoringSystemIndexes())
1228                 in_place_update = true;
1229         /* Allocate a new relfilenode */
1230         newrelfilenode = newoid();
1231         /* update pg_class tuple with new relfilenode */
1232         if (!in_place_update)
1233         {
1234                 classTuple = heap_copytuple(&lockTupleData);
1235                 ReleaseBuffer(buffer);
1236                 ((Form_pg_class) GETSTRUCT(classTuple))->relfilenode = newrelfilenode;
1237                 simple_heap_update(pg_class, &classTuple->t_self, classTuple);
1238         }
1239         /* schedule unlinking old relfilenode */
1240         smgrunlink(DEFAULT_SMGR, relation);
1241         /* create another storage file. Is it a little ugly ? */
1242         memcpy((char *) &workrel, relation, sizeof(RelationData));
1243         workrel.rd_node.relNode = newrelfilenode;
1244         heap_storage_create(&workrel);
1245         smgrclose(DEFAULT_SMGR, &workrel);
1246         /* update pg_class tuple with new relfilenode in place */
1247         if (in_place_update)
1248         {
1249                 classTuple = &lockTupleData;
1250                 /* Send out shared cache inval if necessary */
1251                 if (!IsBootstrapProcessingMode())
1252                         CacheInvalidateHeapTuple(pg_class, classTuple);
1253                 /* Update the buffer in-place */
1254                 LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
1255                 ((Form_pg_class) GETSTRUCT(classTuple))->relfilenode = newrelfilenode;
1256                 LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1257                 WriteBuffer(buffer);
1258                 BufferSync();
1259         }
1260         /* Keep the catalog indices up to date */
1261         if (!in_place_update && pg_class->rd_rel->relhasindex)
1262         {
1263                 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
1264                                                    idescs);
1265                 CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, classTuple);
1266                 CatalogCloseIndices(Num_pg_class_indices, idescs);
1267         }
1268         heap_close(pg_class, NoLock);
1269         if (!in_place_update)
1270                 heap_freetuple(classTuple);
1271         /* Make sure the relfilenode change */
1272         CommandCounterIncrement();
1273 }
1274
1275
1276 /* ----------------
1277  *              UpdateStats
1278  *
1279  * Update pg_class' relpages and reltuples statistics for the given relation
1280  * (which can be either a table or an index).  Note that this is not used
1281  * in the context of VACUUM.
1282  * ----------------
1283  */
1284 void
1285 UpdateStats(Oid relid, double reltuples)
1286 {
1287         Relation        whichRel;
1288         Relation        pg_class;
1289         HeapTuple       tuple;
1290         HeapTuple       newtup;
1291         BlockNumber relpages;
1292         int                     i;
1293         Form_pg_class rd_rel;
1294         Relation        idescs[Num_pg_class_indices];
1295         Datum           values[Natts_pg_class];
1296         char            nulls[Natts_pg_class];
1297         char            replace[Natts_pg_class];
1298         HeapScanDesc pg_class_scan = NULL;
1299         bool            in_place_upd;
1300
1301         /*
1302          * This routine handles updates for both the heap and index relation
1303          * statistics.  In order to guarantee that we're able to *see* the
1304          * index relation tuple, we bump the command counter id here.  The
1305          * index relation tuple was created in the current transaction.
1306          */
1307         CommandCounterIncrement();
1308
1309         /*
1310          * CommandCounterIncrement() flushes invalid cache entries, including
1311          * those for the heap and index relations for which we're updating
1312          * statistics.  Now that the cache is flushed, it's safe to open the
1313          * relation again.      We need the relation open in order to figure out
1314          * how many blocks it contains.
1315          */
1316
1317         /*
1318          * Grabbing lock here is probably redundant ...
1319          */
1320         whichRel = relation_open(relid, ShareLock);
1321
1322         /*
1323          * Find the RELATION relation tuple for the given relation.
1324          */
1325         pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
1326
1327         in_place_upd = (IsIgnoringSystemIndexes() || IsReindexProcessing());
1328
1329         if (!in_place_upd)
1330         {
1331                 tuple = SearchSysCacheCopy(RELOID,
1332                                                                    ObjectIdGetDatum(relid),
1333                                                                    0, 0, 0);
1334         }
1335         else
1336         {
1337                 ScanKeyData key[1];
1338
1339                 ScanKeyEntryInitialize(&key[0], 0,
1340                                                            ObjectIdAttributeNumber,
1341                                                            F_OIDEQ,
1342                                                            ObjectIdGetDatum(relid));
1343
1344                 pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key);
1345                 tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
1346         }
1347
1348         if (!HeapTupleIsValid(tuple))
1349         {
1350                 if (pg_class_scan)
1351                         heap_endscan(pg_class_scan);
1352                 heap_close(pg_class, RowExclusiveLock);
1353                 elog(ERROR, "UpdateStats: cannot find relation %u in pg_class",
1354                          relid);
1355         }
1356
1357         /*
1358          * Figure values to insert.
1359          *
1360          * If we found zero tuples in the scan, do NOT believe it; instead put a
1361          * bogus estimate into the statistics fields.  Otherwise, the common
1362          * pattern "CREATE TABLE; CREATE INDEX; insert data" leaves the table
1363          * with zero size statistics until a VACUUM is done.  The optimizer
1364          * will generate very bad plans if the stats claim the table is empty
1365          * when it is actually sizable.  See also CREATE TABLE in heap.c.
1366          *
1367          * Note: this path is also taken during bootstrap, because bootstrap.c
1368          * passes reltuples = 0 after loading a table.  We have to estimate
1369          * some number for reltuples based on the actual number of pages.
1370          */
1371         relpages = RelationGetNumberOfBlocks(whichRel);
1372
1373         if (reltuples == 0)
1374         {
1375                 if (relpages == 0)
1376                 {
1377                         /* Bogus defaults for a virgin table, same as heap.c */
1378                         reltuples = 1000;
1379                         relpages = 10;
1380                 }
1381                 else if (whichRel->rd_rel->relkind == RELKIND_INDEX && relpages <= 2)
1382                 {
1383                         /* Empty index, leave bogus defaults in place */
1384                         reltuples = 1000;
1385                 }
1386                 else
1387                         reltuples = ((double) relpages) * NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts);
1388         }
1389
1390         /*
1391          * We shouldn't have to do this, but we do...  Modify the reldesc in
1392          * place with the new values so that the cache contains the latest
1393          * copy.
1394          */
1395         whichRel->rd_rel->relpages = (int32) relpages;
1396         whichRel->rd_rel->reltuples = reltuples;
1397
1398         /*
1399          * Update statistics in pg_class.
1400          */
1401         if (in_place_upd)
1402         {
1403                 /*
1404                  * At bootstrap time, we don't need to worry about concurrency or
1405                  * visibility of changes, so we cheat.  Also cheat if REINDEX.
1406                  */
1407                 rd_rel = (Form_pg_class) GETSTRUCT(tuple);
1408                 LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE);
1409                 rd_rel->relpages = (int32) relpages;
1410                 rd_rel->reltuples = reltuples;
1411                 LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
1412                 WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
1413                 if (!IsBootstrapProcessingMode())
1414                         CacheInvalidateHeapTuple(pg_class, tuple);
1415         }
1416         else
1417         {
1418                 /* During normal processing, must work harder. */
1419
1420                 for (i = 0; i < Natts_pg_class; i++)
1421                 {
1422                         nulls[i] = ' ';
1423                         replace[i] = ' ';
1424                         values[i] = (Datum) NULL;
1425                 }
1426
1427                 replace[Anum_pg_class_relpages - 1] = 'r';
1428                 values[Anum_pg_class_relpages - 1] = Int32GetDatum((int32) relpages);
1429                 replace[Anum_pg_class_reltuples - 1] = 'r';
1430                 values[Anum_pg_class_reltuples - 1] = Float4GetDatum((float4) reltuples);
1431                 newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace);
1432                 simple_heap_update(pg_class, &tuple->t_self, newtup);
1433                 if (!IsIgnoringSystemIndexes())
1434                 {
1435                         CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
1436                         CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
1437                         CatalogCloseIndices(Num_pg_class_indices, idescs);
1438                 }
1439                 heap_freetuple(newtup);
1440         }
1441
1442         if (!pg_class_scan)
1443                 heap_freetuple(tuple);
1444         else
1445                 heap_endscan(pg_class_scan);
1446
1447         heap_close(pg_class, RowExclusiveLock);
1448         relation_close(whichRel, NoLock);
1449 }
1450
1451
1452 /*
1453  * index_build - invoke access-method-specific index build procedure
1454  */
1455 void
1456 index_build(Relation heapRelation,
1457                         Relation indexRelation,
1458                         IndexInfo *indexInfo)
1459 {
1460         RegProcedure procedure;
1461
1462         /*
1463          * sanity checks
1464          */
1465         Assert(RelationIsValid(indexRelation));
1466         Assert(PointerIsValid(indexRelation->rd_am));
1467
1468         procedure = indexRelation->rd_am->ambuild;
1469         Assert(RegProcedureIsValid(procedure));
1470
1471         /*
1472          * Call the access method's build procedure
1473          */
1474         OidFunctionCall3(procedure,
1475                                          PointerGetDatum(heapRelation),
1476                                          PointerGetDatum(indexRelation),
1477                                          PointerGetDatum(indexInfo));
1478 }
1479
1480
1481 /*
1482  * IndexBuildHeapScan - scan the heap relation to find tuples to be indexed
1483  *
1484  * This is called back from an access-method-specific index build procedure
1485  * after the AM has done whatever setup it needs.  The parent heap relation
1486  * is scanned to find tuples that should be entered into the index.  Each
1487  * such tuple is passed to the AM's callback routine, which does the right
1488  * things to add it to the new index.  After we return, the AM's index
1489  * build procedure does whatever cleanup is needed; in particular, it should
1490  * close the heap and index relations.
1491  *
1492  * The total count of heap tuples is returned.  This is for updating pg_class
1493  * statistics.  (It's annoying not to be able to do that here, but we can't
1494  * do it until after the relation is closed.)  Note that the index AM itself
1495  * must keep track of the number of index tuples; we don't do so here because
1496  * the AM might reject some of the tuples for its own reasons, such as being
1497  * unable to store NULLs.
1498  */
1499 double
1500 IndexBuildHeapScan(Relation heapRelation,
1501                                    Relation indexRelation,
1502                                    IndexInfo *indexInfo,
1503                                    IndexBuildCallback callback,
1504                                    void *callback_state)
1505 {
1506         HeapScanDesc scan;
1507         HeapTuple       heapTuple;
1508         TupleDesc       heapDescriptor;
1509         Datum           attdata[INDEX_MAX_KEYS];
1510         char            nulls[INDEX_MAX_KEYS];
1511         double          reltuples;
1512         List       *predicate = indexInfo->ii_Predicate;
1513         TupleTable      tupleTable;
1514         TupleTableSlot *slot;
1515         ExprContext *econtext;
1516         Snapshot        snapshot;
1517         TransactionId OldestXmin;
1518
1519         /*
1520          * sanity checks
1521          */
1522         Assert(OidIsValid(indexRelation->rd_rel->relam));
1523
1524         heapDescriptor = RelationGetDescr(heapRelation);
1525
1526         /*
1527          * If this is a predicate (partial) index, we will need to evaluate
1528          * the predicate using ExecQual, which requires the current tuple to
1529          * be in a slot of a TupleTable.  In addition, ExecQual must have an
1530          * ExprContext referring to that slot.  Here, we initialize dummy
1531          * TupleTable and ExprContext objects for this purpose. --Nels, Feb 92
1532          *
1533          * We construct the ExprContext anyway since we need a per-tuple
1534          * temporary memory context for function evaluation -- tgl July 00
1535          */
1536         if (predicate != NIL)
1537         {
1538                 tupleTable = ExecCreateTupleTable(1);
1539                 slot = ExecAllocTableSlot(tupleTable);
1540                 ExecSetSlotDescriptor(slot, heapDescriptor, false);
1541         }
1542         else
1543         {
1544                 tupleTable = NULL;
1545                 slot = NULL;
1546         }
1547         econtext = MakeExprContext(slot, TransactionCommandContext);
1548
1549         /*
1550          * Ok, begin our scan of the base relation.  We use SnapshotAny
1551          * because we must retrieve all tuples and do our own time qual
1552          * checks.
1553          */
1554         if (IsBootstrapProcessingMode())
1555         {
1556                 snapshot = SnapshotNow;
1557                 OldestXmin = InvalidTransactionId;
1558         }
1559         else
1560         {
1561                 snapshot = SnapshotAny;
1562                 OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared);
1563         }
1564
1565         scan = heap_beginscan(heapRelation, /* relation */
1566                                                   snapshot,             /* seeself */
1567                                                   0,    /* number of keys */
1568                                                   (ScanKey) NULL);              /* scan key */
1569
1570         reltuples = 0;
1571
1572         /*
1573          * Scan all tuples in the base relation.
1574          */
1575         while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1576         {
1577                 bool            tupleIsAlive;
1578
1579                 CHECK_FOR_INTERRUPTS();
1580
1581                 if (snapshot == SnapshotAny)
1582                 {
1583                         /* do our own time qual check */
1584                         bool            indexIt;
1585                         uint16          sv_infomask;
1586
1587                         /*
1588                          * HeapTupleSatisfiesVacuum may update tuple's hint status
1589                          * bits. We could possibly get away with not locking the
1590                          * buffer here, since caller should hold ShareLock on the
1591                          * relation, but let's be conservative about it.
1592                          */
1593                         LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
1594                         sv_infomask = heapTuple->t_data->t_infomask;
1595
1596                         switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin))
1597                         {
1598                                 case HEAPTUPLE_DEAD:
1599                                         indexIt = false;
1600                                         tupleIsAlive = false;
1601                                         break;
1602                                 case HEAPTUPLE_LIVE:
1603                                         indexIt = true;
1604                                         tupleIsAlive = true;
1605                                         break;
1606                                 case HEAPTUPLE_RECENTLY_DEAD:
1607
1608                                         /*
1609                                          * If tuple is recently deleted then we must index it
1610                                          * anyway to keep VACUUM from complaining.
1611                                          */
1612                                         indexIt = true;
1613                                         tupleIsAlive = false;
1614                                         break;
1615                                 case HEAPTUPLE_INSERT_IN_PROGRESS:
1616
1617                                         /*
1618                                          * Since caller should hold ShareLock or better, we
1619                                          * should not see any tuples inserted by open
1620                                          * transactions --- unless it's our own transaction.
1621                                          * (Consider INSERT followed by CREATE INDEX within a
1622                                          * transaction.)
1623                                          */
1624                                         if (!TransactionIdIsCurrentTransactionId(
1625                                                         HeapTupleHeaderGetXmin(heapTuple->t_data)))
1626                                                 elog(ERROR, "IndexBuildHeapScan: concurrent insert in progress");
1627                                         indexIt = true;
1628                                         tupleIsAlive = true;
1629                                         break;
1630                                 case HEAPTUPLE_DELETE_IN_PROGRESS:
1631
1632                                         /*
1633                                          * Since caller should hold ShareLock or better, we
1634                                          * should not see any tuples deleted by open
1635                                          * transactions --- unless it's our own transaction.
1636                                          * (Consider DELETE followed by CREATE INDEX within a
1637                                          * transaction.)
1638                                          */
1639                                         if (!TransactionIdIsCurrentTransactionId(
1640                                                         HeapTupleHeaderGetXmax(heapTuple->t_data)))
1641                                                 elog(ERROR, "IndexBuildHeapScan: concurrent delete in progress");
1642                                         indexIt = true;
1643                                         tupleIsAlive = false;
1644                                         break;
1645                                 default:
1646                                         elog(ERROR, "Unexpected HeapTupleSatisfiesVacuum result");
1647                                         indexIt = tupleIsAlive = false;         /* keep compiler quiet */
1648                                         break;
1649                         }
1650
1651                         /* check for hint-bit update by HeapTupleSatisfiesVacuum */
1652                         if (sv_infomask != heapTuple->t_data->t_infomask)
1653                                 SetBufferCommitInfoNeedsSave(scan->rs_cbuf);
1654
1655                         LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
1656
1657                         if (!indexIt)
1658                                 continue;
1659                 }
1660                 else
1661                 {
1662                         /* heap_getnext did the time qual check */
1663                         tupleIsAlive = true;
1664                 }
1665
1666                 reltuples += 1;
1667
1668                 MemoryContextReset(econtext->ecxt_per_tuple_memory);
1669
1670                 /*
1671                  * In a partial index, discard tuples that don't satisfy the
1672                  * predicate.  We can also discard recently-dead tuples, since
1673                  * VACUUM doesn't complain about tuple count mismatch for partial
1674                  * indexes.
1675                  */
1676                 if (predicate != NIL)
1677                 {
1678                         if (!tupleIsAlive)
1679                                 continue;
1680                         ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
1681                         if (!ExecQual(predicate, econtext, false))
1682                                 continue;
1683                 }
1684
1685                 /*
1686                  * For the current heap tuple, extract all the attributes we use
1687                  * in this index, and note which are null.      This also performs
1688                  * evaluation of the function, if this is a functional index.
1689                  */
1690                 FormIndexDatum(indexInfo,
1691                                            heapTuple,
1692                                            heapDescriptor,
1693                                            econtext->ecxt_per_tuple_memory,
1694                                            attdata,
1695                                            nulls);
1696
1697                 /*
1698                  * You'd think we should go ahead and build the index tuple here,
1699                  * but some index AMs want to do further processing on the data
1700                  * first.  So pass the attdata and nulls arrays, instead.
1701                  */
1702
1703                 /* Call the AM's callback routine to process the tuple */
1704                 callback(indexRelation, heapTuple, attdata, nulls, tupleIsAlive,
1705                                  callback_state);
1706         }
1707
1708         heap_endscan(scan);
1709
1710         if (predicate != NIL)
1711                 ExecDropTupleTable(tupleTable, true);
1712         FreeExprContext(econtext);
1713
1714         return reltuples;
1715 }
1716
1717
1718 /*
1719  * IndexGetRelation: given an index's relation OID, get the OID of the
1720  * relation it is an index on.  Uses the system cache.
1721  */
1722 static Oid
1723 IndexGetRelation(Oid indexId)
1724 {
1725         HeapTuple       tuple;
1726         Form_pg_index index;
1727         Oid                     result;
1728
1729         tuple = SearchSysCache(INDEXRELID,
1730                                                    ObjectIdGetDatum(indexId),
1731                                                    0, 0, 0);
1732         if (!HeapTupleIsValid(tuple))
1733                 elog(ERROR, "IndexGetRelation: can't find index id %u",
1734                          indexId);
1735         index = (Form_pg_index) GETSTRUCT(tuple);
1736         Assert(index->indexrelid == indexId);
1737
1738         result = index->indrelid;
1739         ReleaseSysCache(tuple);
1740         return result;
1741 }
1742
1743 /* ---------------------------------
1744  * activate_index -- activate/deactivate the specified index.
1745  *              Note that currently PostgreSQL doesn't hold the
1746  *              status per index
1747  * ---------------------------------
1748  */
1749 static bool
1750 activate_index(Oid indexId, bool activate, bool inplace)
1751 {
1752         if (!activate)                          /* Currently does nothing */
1753                 return true;
1754         return reindex_index(indexId, false, inplace);
1755 }
1756
1757 /* --------------------------------
1758  * reindex_index - This routine is used to recreate an index
1759  * --------------------------------
1760  */
1761 bool
1762 reindex_index(Oid indexId, bool force, bool inplace)
1763 {
1764         Relation        iRel,
1765                                 heapRelation;
1766         IndexInfo  *indexInfo;
1767         Oid                     heapId;
1768         bool            old;
1769
1770         /*
1771          * REINDEX within a transaction block is dangerous, because if the
1772          * transaction is later rolled back we have no way to undo truncation
1773          * of the index's physical file.  Disallow it.
1774          *
1775          * XXX if we're not doing an inplace rebuild, wouldn't this be okay?
1776          */
1777         if (IsTransactionBlock())
1778                 elog(ERROR, "REINDEX cannot run inside a transaction block");
1779
1780         /*
1781          * Open our index relation and get an exclusive lock on it.
1782          *
1783          * Note: doing this before opening the parent heap relation means
1784          * there's a possibility for deadlock failure against another xact
1785          * that is doing normal accesses to the heap and index.  However,
1786          * it's not real clear why you'd be needing to do REINDEX on a table
1787          * that's in active use, so I'd rather have the protection of making
1788          * sure the index is locked down.
1789          */
1790         iRel = index_open(indexId);
1791         if (iRel == NULL)
1792                 elog(ERROR, "reindex_index: can't open index relation");
1793         LockRelation(iRel, AccessExclusiveLock);
1794
1795         old = SetReindexProcessing(true);
1796
1797         /* Get OID of index's parent table */
1798         heapId = iRel->rd_index->indrelid;
1799         /* Fetch info needed for index_build */
1800         indexInfo = BuildIndexInfo(iRel->rd_index);
1801
1802         /* Open the parent heap relation */
1803         heapRelation = heap_open(heapId, ExclusiveLock);
1804         if (heapRelation == NULL)
1805                 elog(ERROR, "reindex_index: can't open heap relation");
1806
1807         /*
1808          * Force inplace processing if it's a shared index.  Necessary because
1809          * we have no way to update relfilenode in other databases.
1810          */
1811         if (iRel->rd_rel->relisshared)
1812                 inplace = true;
1813
1814         if (inplace)
1815         {
1816                 /*
1817                  * Release any buffers associated with this index.      If they're
1818                  * dirty, they're just dropped without bothering to flush to disk.
1819                  */
1820                 DropRelationBuffers(iRel);
1821
1822                 /* Now truncate the actual data and set blocks to zero */
1823                 smgrtruncate(DEFAULT_SMGR, iRel, 0);
1824                 iRel->rd_nblocks = 0;
1825                 iRel->rd_targblock = InvalidBlockNumber;
1826         }
1827         else
1828         {
1829                 /*
1830                  * We'll build a new physical relation for the index.
1831                  */
1832                 setNewRelfilenode(iRel);
1833         }
1834
1835         /* Initialize the index and rebuild */
1836         index_build(heapRelation, iRel, indexInfo);
1837
1838         /*
1839          * index_build will close both the heap and index relations (but not
1840          * give up the locks we hold on them).  So we're done.
1841          */
1842
1843         SetReindexProcessing(old);
1844
1845         return true;
1846 }
1847
1848 /*
1849  * ----------------------------
1850  * activate_indexes_of_a_table
1851  *      activate/deactivate indexes of the specified table.
1852  * ----------------------------
1853  */
1854 bool
1855 activate_indexes_of_a_table(Oid relid, bool activate)
1856 {
1857         if (IndexesAreActive(relid, true))
1858         {
1859                 if (!activate)
1860                         setRelhasindex(relid, false, false, InvalidOid);
1861                 else
1862                         return false;
1863         }
1864         else
1865         {
1866                 if (activate)
1867                         reindex_relation(relid, false);
1868                 else
1869                         return false;
1870         }
1871         return true;
1872 }
1873
1874 /* --------------------------------
1875  * reindex_relation - This routine is used to recreate indexes
1876  * of a relation.
1877  * --------------------------------
1878  */
1879 bool
1880 reindex_relation(Oid relid, bool force)
1881 {
1882         Relation        indexRelation;
1883         ScanKeyData entry;
1884         HeapScanDesc scan;
1885         HeapTuple       indexTuple;
1886         bool            old,
1887                                 reindexed;
1888         bool            deactivate_needed,
1889                                 overwrite,
1890                                 upd_pg_class_inplace;
1891         Relation        rel;
1892
1893         overwrite = upd_pg_class_inplace = deactivate_needed = false;
1894
1895         /*
1896          * avoid heap_update() pg_class tuples while processing reindex for
1897          * pg_class.
1898          */
1899         if (IsIgnoringSystemIndexes())
1900                 upd_pg_class_inplace = true;
1901
1902         /*
1903          * Ensure to hold an exclusive lock throughout the transaction. The
1904          * lock could be less intensive but now it's AccessExclusiveLock for
1905          * simplicity.
1906          */
1907         rel = heap_open(relid, AccessExclusiveLock);
1908
1909         /*
1910          * ignore the indexes of the target system relation while processing
1911          * reindex.
1912          */
1913         if (!IsIgnoringSystemIndexes() && IsSystemRelation(rel))
1914                 deactivate_needed = true;
1915 #ifndef ENABLE_REINDEX_NAILED_RELATIONS
1916
1917         /*
1918          * nailed relations are never updated. We couldn't keep the
1919          * consistency between the relation descriptors and pg_class tuples.
1920          */
1921         if (rel->rd_isnailed)
1922         {
1923                 if (IsIgnoringSystemIndexes())
1924                 {
1925                         overwrite = true;
1926                         deactivate_needed = true;
1927                 }
1928                 else
1929                         elog(ERROR, "the target relation %u is nailed", relid);
1930         }
1931 #endif   /* ENABLE_REINDEX_NAILED_RELATIONS */
1932
1933         /*
1934          * Shared system indexes must be overwritten because it's impossible
1935          * to update pg_class tuples of all databases.
1936          */
1937         if (rel->rd_rel->relisshared)
1938         {
1939                 if (IsIgnoringSystemIndexes())
1940                 {
1941                         overwrite = true;
1942                         deactivate_needed = true;
1943                 }
1944                 else
1945                         elog(ERROR, "the target relation %u is shared", relid);
1946         }
1947
1948         /*
1949          * Continue to hold the lock.
1950          */
1951         heap_close(rel, NoLock);
1952
1953         old = SetReindexProcessing(true);
1954         if (deactivate_needed)
1955         {
1956                 if (IndexesAreActive(relid, upd_pg_class_inplace))
1957                 {
1958                         if (!force)
1959                         {
1960                                 SetReindexProcessing(old);
1961                                 return false;
1962                         }
1963                         activate_indexes_of_a_table(relid, false);
1964                         CommandCounterIncrement();
1965                 }
1966         }
1967
1968         indexRelation = heap_openr(IndexRelationName, AccessShareLock);
1969         ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
1970                                                    F_OIDEQ, ObjectIdGetDatum(relid));
1971         scan = heap_beginscan(indexRelation, SnapshotNow, 1, &entry);
1972         reindexed = false;
1973         while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1974         {
1975                 Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple);
1976
1977                 if (activate_index(index->indexrelid, true, overwrite))
1978                         reindexed = true;
1979                 else
1980                 {
1981                         reindexed = false;
1982                         break;
1983                 }
1984         }
1985         heap_endscan(scan);
1986         heap_close(indexRelation, AccessShareLock);
1987         if (reindexed)
1988         {
1989                 /*
1990                  * Ok,we could use the reindexed indexes of the target system
1991                  * relation now.
1992                  */
1993                 if (deactivate_needed)
1994                 {
1995                         if (!overwrite && relid == RelOid_pg_class)
1996                         {
1997                                 /*
1998                                  * For pg_class, relhasindex should be set to true here in
1999                                  * place.
2000                                  */
2001                                 setRelhasindex(relid, true, false, InvalidOid);
2002                                 CommandCounterIncrement();
2003
2004                                 /*
2005                                  * However the following setRelhasindex() is needed to
2006                                  * keep consistency with WAL.
2007                                  */
2008                         }
2009                         setRelhasindex(relid, true, false, InvalidOid);
2010                 }
2011         }
2012         SetReindexProcessing(old);
2013
2014         return reindexed;
2015 }