88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.201 2001/07/02 20:50:46 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.202 2001/07/11 18:38:07 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
3434#include "catalog/catalog.h"
3535#include "catalog/catname.h"
3636#include "catalog/index.h"
37+ #include "catalog/pg_index.h"
3738#include "commands/vacuum.h"
39+ #include "executor/executor.h"
3840#include "miscadmin.h"
3941#include "nodes/execnodes.h"
4042#include "storage/freespace.h"
4143#include "storage/sinval.h"
4244#include "storage/smgr.h"
45+ #include "tcop/pquery.h"
4346#include "tcop/tcopprot.h"
4447#include "utils/acl.h"
4548#include "utils/builtins.h"
@@ -153,8 +156,7 @@ static VacPage copy_vac_page(VacPage vacpage);
153156static void vpage_insert (VacPageList vacpagelist , VacPage vpnew );
154157static void get_indices (Relation relation , int * nindices , Relation * * Irel );
155158static void close_indices (int nindices , Relation * Irel );
156- static IndexInfo * * get_index_desc (Relation onerel , int nindices ,
157- Relation * Irel );
159+ static bool is_partial_index (Relation indrel );
158160static void * vac_bsearch (const void * key , const void * base ,
159161 size_t nelem , size_t size ,
160162 int (* compar ) (const void * , const void * ));
@@ -504,7 +506,7 @@ vacuum_rel(Oid relid)
504506 IsSystemRelationName (RelationGetRelationName (onerel )))
505507 reindex = true;
506508
507- /* Now open indices */
509+ /* Now open all indices of the relation */
508510 nindices = 0 ;
509511 Irel = (Relation * ) NULL ;
510512 get_indices (onerel , & nindices , & Irel );
@@ -524,8 +526,7 @@ vacuum_rel(Oid relid)
524526 */
525527 if (reindex )
526528 {
527- for (i = 0 ; i < nindices ; i ++ )
528- index_close (Irel [i ]);
529+ close_indices (nindices , Irel );
529530 Irel = (Relation * ) NULL ;
530531 activate_indexes_of_a_table (relid , false);
531532 }
@@ -553,11 +554,11 @@ vacuum_rel(Oid relid)
553554 /* Try to shrink heap */
554555 repair_frag (vacrelstats , onerel , & vacuum_pages , & fraged_pages ,
555556 nindices , Irel );
557+ close_indices (nindices , Irel );
556558 }
557559 else
558560 {
559- if (Irel != (Relation * ) NULL )
560- close_indices (nindices , Irel );
561+ close_indices (nindices , Irel );
561562 if (vacuum_pages .num_pages > 0 )
562563 {
563564 /* Clean pages from vacuum_pages list */
@@ -1089,10 +1090,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
10891090 HeapTupleData tuple ,
10901091 newtup ;
10911092 TupleDesc tupdesc ;
1092- IndexInfo * * indexInfo = NULL ;
1093- Datum idatum [ INDEX_MAX_KEYS ] ;
1094- char inulls [ INDEX_MAX_KEYS ] ;
1095- InsertIndexResult iresult ;
1093+ ResultRelInfo * resultRelInfo ;
1094+ EState * estate ;
1095+ TupleTable tupleTable ;
1096+ TupleTableSlot * slot ;
10961097 VacPageListData Nvacpagelist ;
10971098 VacPage cur_page = NULL ,
10981099 last_vacuum_page ,
@@ -1119,8 +1120,26 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
11191120
11201121 tupdesc = RelationGetDescr (onerel );
11211122
1122- if (Irel != (Relation * ) NULL ) /* preparation for index' inserts */
1123- indexInfo = get_index_desc (onerel , nindices , Irel );
1123+ /*
1124+ * We need a ResultRelInfo and an EState so we can use the regular
1125+ * executor's index-entry-making machinery.
1126+ */
1127+ resultRelInfo = makeNode (ResultRelInfo );
1128+ resultRelInfo -> ri_RangeTableIndex = 1 ; /* dummy */
1129+ resultRelInfo -> ri_RelationDesc = onerel ;
1130+ resultRelInfo -> ri_TrigDesc = NULL ; /* we don't fire triggers */
1131+
1132+ ExecOpenIndices (resultRelInfo );
1133+
1134+ estate = CreateExecutorState ();
1135+ estate -> es_result_relations = resultRelInfo ;
1136+ estate -> es_num_result_relations = 1 ;
1137+ estate -> es_result_relation_info = resultRelInfo ;
1138+
1139+ /* Set up a dummy tuple table too */
1140+ tupleTable = ExecCreateTupleTable (1 );
1141+ slot = ExecAllocTableSlot (tupleTable );
1142+ ExecSetSlotDescriptor (slot , tupdesc , false);
11241143
11251144 Nvacpagelist .num_pages = 0 ;
11261145 num_fraged_pages = fraged_pages -> num_pages ;
@@ -1645,35 +1664,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
16451664 if (cur_buffer != Cbuf )
16461665 LockBuffer (Cbuf , BUFFER_LOCK_UNLOCK );
16471666
1648- if (Irel != (Relation * ) NULL )
1667+ /* Create index entries for the moved tuple */
1668+ if (resultRelInfo -> ri_NumIndices > 0 )
16491669 {
1650-
1651- /*
1652- * XXX using CurrentMemoryContext here means
1653- * intra-vacuum memory leak for functional
1654- * indexes. Should fix someday.
1655- *
1656- * XXX This code fails to handle partial indexes!
1657- * Probably should change it to use
1658- * ExecOpenIndices.
1659- */
1660- for (i = 0 ; i < nindices ; i ++ )
1661- {
1662- FormIndexDatum (indexInfo [i ],
1663- & newtup ,
1664- tupdesc ,
1665- CurrentMemoryContext ,
1666- idatum ,
1667- inulls );
1668- iresult = index_insert (Irel [i ],
1669- idatum ,
1670- inulls ,
1671- & newtup .t_self ,
1672- onerel );
1673- if (iresult )
1674- pfree (iresult );
1675- }
1670+ ExecStoreTuple (& newtup , slot , InvalidBuffer , false);
1671+ ExecInsertIndexTuples (slot , & (newtup .t_self ),
1672+ estate , true);
16761673 }
1674+
16771675 WriteBuffer (cur_buffer );
16781676 WriteBuffer (Cbuf );
16791677 }
@@ -1780,34 +1778,11 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
17801778 LockBuffer (buf , BUFFER_LOCK_UNLOCK );
17811779
17821780 /* insert index' tuples if needed */
1783- if (Irel != ( Relation * ) NULL )
1781+ if (resultRelInfo -> ri_NumIndices > 0 )
17841782 {
1785-
1786- /*
1787- * XXX using CurrentMemoryContext here means intra-vacuum
1788- * memory leak for functional indexes. Should fix someday.
1789- *
1790- * XXX This code fails to handle partial indexes! Probably
1791- * should change it to use ExecOpenIndices.
1792- */
1793- for (i = 0 ; i < nindices ; i ++ )
1794- {
1795- FormIndexDatum (indexInfo [i ],
1796- & newtup ,
1797- tupdesc ,
1798- CurrentMemoryContext ,
1799- idatum ,
1800- inulls );
1801- iresult = index_insert (Irel [i ],
1802- idatum ,
1803- inulls ,
1804- & newtup .t_self ,
1805- onerel );
1806- if (iresult )
1807- pfree (iresult );
1808- }
1783+ ExecStoreTuple (& newtup , slot , InvalidBuffer , false);
1784+ ExecInsertIndexTuples (slot , & (newtup .t_self ), estate , true);
18091785 }
1810-
18111786 } /* walk along page */
18121787
18131788 if (offnum < maxoff && keep_tuples > 0 )
@@ -2095,15 +2070,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
20952070 vacrelstats -> rel_pages = blkno ; /* set new number of blocks */
20962071 }
20972072
2098- if (Irel != (Relation * ) NULL ) /* pfree index' allocations */
2099- {
2100- close_indices (nindices , Irel );
2101- pfree (indexInfo );
2102- }
2103-
2073+ /* clean up */
21042074 pfree (vacpage );
21052075 if (vacrelstats -> vtlinks != NULL )
21062076 pfree (vacrelstats -> vtlinks );
2077+
2078+ ExecDropTupleTable (tupleTable , true);
2079+
2080+ ExecCloseIndices (resultRelInfo );
21072081}
21082082
21092083/*
@@ -2200,8 +2174,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
22002174}
22012175
22022176/*
2203- * _scan_index() -- scan one index relation to update statistic.
2204- *
2177+ * scan_index() -- scan one index relation to update statistic.
22052178 */
22062179static void
22072180scan_index (Relation indrel , double num_tuples )
@@ -2235,11 +2208,18 @@ scan_index(Relation indrel, double num_tuples)
22352208 RelationGetRelationName (indrel ), nipages , nitups ,
22362209 show_rusage (& ru0 ));
22372210
2211+ /*
2212+ * Check for tuple count mismatch. If the index is partial, then
2213+ * it's OK for it to have fewer tuples than the heap; else we got trouble.
2214+ */
22382215 if (nitups != num_tuples )
2239- elog (NOTICE , "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
2216+ {
2217+ if (nitups > num_tuples ||
2218+ ! is_partial_index (indrel ))
2219+ elog (NOTICE , "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
22402220\n\tRecreate the index." ,
2241- RelationGetRelationName (indrel ), nitups , num_tuples );
2242-
2221+ RelationGetRelationName (indrel ), nitups , num_tuples );
2222+ }
22432223}
22442224
22452225/*
@@ -2315,11 +2295,18 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
23152295 num_index_tuples - keep_tuples , tups_vacuumed ,
23162296 show_rusage (& ru0 ));
23172297
2298+ /*
2299+ * Check for tuple count mismatch. If the index is partial, then
2300+ * it's OK for it to have fewer tuples than the heap; else we got trouble.
2301+ */
23182302 if (num_index_tuples != num_tuples + keep_tuples )
2319- elog (NOTICE , "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
2303+ {
2304+ if (num_index_tuples > num_tuples + keep_tuples ||
2305+ ! is_partial_index (indrel ))
2306+ elog (NOTICE , "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
23202307\n\tRecreate the index." ,
2321- RelationGetRelationName (indrel ), num_index_tuples , num_tuples );
2322-
2308+ RelationGetRelationName (indrel ), num_index_tuples , num_tuples );
2309+ }
23232310}
23242311
23252312/*
@@ -2640,42 +2627,34 @@ get_indices(Relation relation, int *nindices, Relation **Irel)
26402627static void
26412628close_indices (int nindices , Relation * Irel )
26422629{
2643-
26442630 if (Irel == (Relation * ) NULL )
26452631 return ;
26462632
26472633 while (nindices -- )
26482634 index_close (Irel [nindices ]);
26492635 pfree (Irel );
2650-
26512636}
26522637
26532638
2654- /*
2655- * Obtain IndexInfo data for each index on the rel
2656- */
2657- static IndexInfo * *
2658- get_index_desc (Relation onerel , int nindices , Relation * Irel )
2639+ static bool
2640+ is_partial_index (Relation indrel )
26592641{
2660- IndexInfo * * indexInfo ;
2661- int i ;
2642+ bool result ;
26622643 HeapTuple cachetuple ;
2644+ Form_pg_index indexStruct ;
26632645
2664- indexInfo = (IndexInfo * * ) palloc (nindices * sizeof (IndexInfo * ));
2646+ cachetuple = SearchSysCache (INDEXRELID ,
2647+ ObjectIdGetDatum (RelationGetRelid (indrel )),
2648+ 0 , 0 , 0 );
2649+ if (!HeapTupleIsValid (cachetuple ))
2650+ elog (ERROR , "is_partial_index: index %u not found" ,
2651+ RelationGetRelid (indrel ));
2652+ indexStruct = (Form_pg_index ) GETSTRUCT (cachetuple );
26652653
2666- for (i = 0 ; i < nindices ; i ++ )
2667- {
2668- cachetuple = SearchSysCache (INDEXRELID ,
2669- ObjectIdGetDatum (RelationGetRelid (Irel [i ])),
2670- 0 , 0 , 0 );
2671- if (!HeapTupleIsValid (cachetuple ))
2672- elog (ERROR , "get_index_desc: index %u not found" ,
2673- RelationGetRelid (Irel [i ]));
2674- indexInfo [i ] = BuildIndexInfo (cachetuple );
2675- ReleaseSysCache (cachetuple );
2676- }
2654+ result = (VARSIZE (& indexStruct -> indpred ) != 0 );
26772655
2678- return indexInfo ;
2656+ ReleaseSysCache (cachetuple );
2657+ return result ;
26792658}
26802659
26812660
0 commit comments