Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 11ac469

Browse files
committed
Remove direct calls of index_insert(), instead use ExecInsertIndexTuples().
This makes VACUUM work properly with partial indexes, and avoids memory leakage with functional indexes. Also, suppress complaint about fewer index tuples than heap tuples when the index is a partial index. From Martijn van Oosterhout.
1 parent c4bde42 commit 11ac469

File tree

1 file changed

+82
-103
lines changed

1 file changed

+82
-103
lines changed

src/backend/commands/vacuum.c

+82-103
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
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
*/
@@ -34,12 +34,15 @@
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);
153156
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
154157
static void get_indices(Relation relation, int *nindices, Relation **Irel);
155158
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);
158160
static 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
*/
22062179
static void
22072180
scan_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)
26402627
static void
26412628
close_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

Comments
 (0)