8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
34
34
#include "catalog/catalog.h"
35
35
#include "catalog/catname.h"
36
36
#include "catalog/index.h"
37
+ #include "catalog/pg_index.h"
37
38
#include "commands/vacuum.h"
39
+ #include "executor/executor.h"
38
40
#include "miscadmin.h"
39
41
#include "nodes/execnodes.h"
40
42
#include "storage/freespace.h"
41
43
#include "storage/sinval.h"
42
44
#include "storage/smgr.h"
45
+ #include "tcop/pquery.h"
43
46
#include "tcop/tcopprot.h"
44
47
#include "utils/acl.h"
45
48
#include "utils/builtins.h"
@@ -153,8 +156,7 @@ static VacPage copy_vac_page(VacPage vacpage);
153
156
static void vpage_insert (VacPageList vacpagelist , VacPage vpnew );
154
157
static void get_indices (Relation relation , int * nindices , Relation * * Irel );
155
158
static 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 );
158
160
static void * vac_bsearch (const void * key , const void * base ,
159
161
size_t nelem , size_t size ,
160
162
int (* compar ) (const void * , const void * ));
@@ -504,7 +506,7 @@ vacuum_rel(Oid relid)
504
506
IsSystemRelationName (RelationGetRelationName (onerel )))
505
507
reindex = true;
506
508
507
- /* Now open indices */
509
+ /* Now open all indices of the relation */
508
510
nindices = 0 ;
509
511
Irel = (Relation * ) NULL ;
510
512
get_indices (onerel , & nindices , & Irel );
@@ -524,8 +526,7 @@ vacuum_rel(Oid relid)
524
526
*/
525
527
if (reindex )
526
528
{
527
- for (i = 0 ; i < nindices ; i ++ )
528
- index_close (Irel [i ]);
529
+ close_indices (nindices , Irel );
529
530
Irel = (Relation * ) NULL ;
530
531
activate_indexes_of_a_table (relid , false);
531
532
}
@@ -553,11 +554,11 @@ vacuum_rel(Oid relid)
553
554
/* Try to shrink heap */
554
555
repair_frag (vacrelstats , onerel , & vacuum_pages , & fraged_pages ,
555
556
nindices , Irel );
557
+ close_indices (nindices , Irel );
556
558
}
557
559
else
558
560
{
559
- if (Irel != (Relation * ) NULL )
560
- close_indices (nindices , Irel );
561
+ close_indices (nindices , Irel );
561
562
if (vacuum_pages .num_pages > 0 )
562
563
{
563
564
/* Clean pages from vacuum_pages list */
@@ -1089,10 +1090,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
1089
1090
HeapTupleData tuple ,
1090
1091
newtup ;
1091
1092
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 ;
1096
1097
VacPageListData Nvacpagelist ;
1097
1098
VacPage cur_page = NULL ,
1098
1099
last_vacuum_page ,
@@ -1119,8 +1120,26 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
1119
1120
1120
1121
tupdesc = RelationGetDescr (onerel );
1121
1122
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);
1124
1143
1125
1144
Nvacpagelist .num_pages = 0 ;
1126
1145
num_fraged_pages = fraged_pages -> num_pages ;
@@ -1645,35 +1664,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
1645
1664
if (cur_buffer != Cbuf )
1646
1665
LockBuffer (Cbuf , BUFFER_LOCK_UNLOCK );
1647
1666
1648
- if (Irel != (Relation * ) NULL )
1667
+ /* Create index entries for the moved tuple */
1668
+ if (resultRelInfo -> ri_NumIndices > 0 )
1649
1669
{
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);
1676
1673
}
1674
+
1677
1675
WriteBuffer (cur_buffer );
1678
1676
WriteBuffer (Cbuf );
1679
1677
}
@@ -1780,34 +1778,11 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
1780
1778
LockBuffer (buf , BUFFER_LOCK_UNLOCK );
1781
1779
1782
1780
/* insert index' tuples if needed */
1783
- if (Irel != ( Relation * ) NULL )
1781
+ if (resultRelInfo -> ri_NumIndices > 0 )
1784
1782
{
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);
1809
1785
}
1810
-
1811
1786
} /* walk along page */
1812
1787
1813
1788
if (offnum < maxoff && keep_tuples > 0 )
@@ -2095,15 +2070,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
2095
2070
vacrelstats -> rel_pages = blkno ; /* set new number of blocks */
2096
2071
}
2097
2072
2098
- if (Irel != (Relation * ) NULL ) /* pfree index' allocations */
2099
- {
2100
- close_indices (nindices , Irel );
2101
- pfree (indexInfo );
2102
- }
2103
-
2073
+ /* clean up */
2104
2074
pfree (vacpage );
2105
2075
if (vacrelstats -> vtlinks != NULL )
2106
2076
pfree (vacrelstats -> vtlinks );
2077
+
2078
+ ExecDropTupleTable (tupleTable , true);
2079
+
2080
+ ExecCloseIndices (resultRelInfo );
2107
2081
}
2108
2082
2109
2083
/*
@@ -2200,8 +2174,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
2200
2174
}
2201
2175
2202
2176
/*
2203
- * _scan_index() -- scan one index relation to update statistic.
2204
- *
2177
+ * scan_index() -- scan one index relation to update statistic.
2205
2178
*/
2206
2179
static void
2207
2180
scan_index (Relation indrel , double num_tuples )
@@ -2235,11 +2208,18 @@ scan_index(Relation indrel, double num_tuples)
2235
2208
RelationGetRelationName (indrel ), nipages , nitups ,
2236
2209
show_rusage (& ru0 ));
2237
2210
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
+ */
2238
2215
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).\
2240
2220
\n\tRecreate the index." ,
2241
- RelationGetRelationName (indrel ), nitups , num_tuples );
2242
-
2221
+ RelationGetRelationName (indrel ), nitups , num_tuples );
2222
+ }
2243
2223
}
2244
2224
2245
2225
/*
@@ -2315,11 +2295,18 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
2315
2295
num_index_tuples - keep_tuples , tups_vacuumed ,
2316
2296
show_rusage (& ru0 ));
2317
2297
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
+ */
2318
2302
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).\
2320
2307
\n\tRecreate the index." ,
2321
- RelationGetRelationName (indrel ), num_index_tuples , num_tuples );
2322
-
2308
+ RelationGetRelationName (indrel ), num_index_tuples , num_tuples );
2309
+ }
2323
2310
}
2324
2311
2325
2312
/*
@@ -2640,42 +2627,34 @@ get_indices(Relation relation, int *nindices, Relation **Irel)
2640
2627
static void
2641
2628
close_indices (int nindices , Relation * Irel )
2642
2629
{
2643
-
2644
2630
if (Irel == (Relation * ) NULL )
2645
2631
return ;
2646
2632
2647
2633
while (nindices -- )
2648
2634
index_close (Irel [nindices ]);
2649
2635
pfree (Irel );
2650
-
2651
2636
}
2652
2637
2653
2638
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 )
2659
2641
{
2660
- IndexInfo * * indexInfo ;
2661
- int i ;
2642
+ bool result ;
2662
2643
HeapTuple cachetuple ;
2644
+ Form_pg_index indexStruct ;
2663
2645
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 );
2665
2653
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 );
2677
2655
2678
- return indexInfo ;
2656
+ ReleaseSysCache (cachetuple );
2657
+ return result ;
2679
2658
}
2680
2659
2681
2660
0 commit comments