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

Commit d9f7431

Browse files
committed
Ported BTREE patch to PGPRO10 (task 1126)
1 parent 185d62a commit d9f7431

File tree

6 files changed

+154
-12
lines changed

6 files changed

+154
-12
lines changed

src/backend/access/common/indextuple.c

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,25 @@ IndexTuple
3838
index_form_tuple(TupleDesc tupleDescriptor,
3939
Datum *values,
4040
bool *isnull)
41+
{
42+
return index_form_tuple_extended(tupleDescriptor, values, isnull, tupleDescriptor->natts, NULL);
43+
}
44+
45+
/*
46+
* Workhorse for index_form_tuple().
47+
* This function is needed primarily to avoid de-toasting of the
48+
* included attributes for indexes with included columns.
49+
*
50+
* If sz_check_failed == NULL, then in case of tuple being too big we will print
51+
* an error. If it's a pointer to a bool, then we won't print an error but we will
52+
* make the bool TRUE if the tuple is too big and FALSE if it's all good.
53+
*/
54+
IndexTuple
55+
index_form_tuple_extended(TupleDesc tupleDescriptor,
56+
Datum *values,
57+
bool *isnull,
58+
int nkeyattrs,
59+
bool *sz_check_failed)
4160
{
4261
char *tp; /* tuple pointer */
4362
IndexTuple tuple; /* return tuple */
@@ -61,6 +80,8 @@ index_form_tuple(TupleDesc tupleDescriptor,
6180
errmsg("number of index columns (%d) exceeds limit (%d)",
6281
numberOfAttributes, INDEX_MAX_KEYS)));
6382

83+
Assert (nkeyattrs <= tupleDescriptor->natts);
84+
6485
#ifdef TOAST_INDEX_HACK
6586
for (i = 0; i < numberOfAttributes; i++)
6687
{
@@ -73,6 +94,10 @@ index_form_tuple(TupleDesc tupleDescriptor,
7394
if (isnull[i] || att->attlen != -1)
7495
continue;
7596

97+
/* Do not de-toast included attibutes. */
98+
if (i >= nkeyattrs)
99+
continue;
100+
76101
/*
77102
* If value is stored EXTERNAL, must fetch it so we are not depending
78103
* on outside storage. This should be improved someday.
@@ -133,6 +158,7 @@ index_form_tuple(TupleDesc tupleDescriptor,
133158
tp = (char *) palloc0(size);
134159
tuple = (IndexTuple) tp;
135160

161+
136162
heap_fill_tuple(tupleDescriptor,
137163
#ifdef TOAST_INDEX_HACK
138164
untoasted_values,
@@ -162,20 +188,23 @@ index_form_tuple(TupleDesc tupleDescriptor,
162188
if (tupmask & HEAP_HASVARWIDTH)
163189
infomask |= INDEX_VAR_MASK;
164190

165-
/* Also assert we got rid of external attributes */
166-
#ifdef TOAST_INDEX_HACK
167-
Assert((tupmask & HEAP_HASEXTERNAL) == 0);
168-
#endif
169-
170191
/*
171192
* Here we make sure that the size will fit in the field reserved for it
172193
* in t_info.
173194
*/
195+
if(sz_check_failed)
196+
*sz_check_failed = false;
197+
174198
if ((size & INDEX_SIZE_MASK) != size)
175-
ereport(ERROR,
176-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
177-
errmsg("index row requires %zu bytes, maximum size is %zu",
178-
size, (Size) INDEX_SIZE_MASK)));
199+
{
200+
if(sz_check_failed)
201+
*sz_check_failed = true;
202+
else
203+
ereport(ERROR,
204+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
205+
errmsg("index row requires %zu bytes, maximum size is %zu",
206+
size, (Size) INDEX_SIZE_MASK)));
207+
}
179208

180209
infomask |= size;
181210

src/backend/access/nbtree/nbtinsert.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,48 @@ static bool _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
8585
static void _bt_vacuum_one_page(Relation rel, Buffer buffer, Relation heapRel);
8686

8787

88+
/*
89+
* tuple_too_long_for_btree() -- returns TRUE if too long, FALSE if not
90+
*
91+
* Code for the check taken from _bt_findinsertloc() and _bt_doinsert()
92+
*/
93+
bool
94+
tuple_too_long_for_btree(Relation rel, IndexTuple itup)
95+
{
96+
Buffer buf;
97+
Page page;
98+
Size itemsz;
99+
int indnkeyatts;
100+
ScanKey itup_scankey;
101+
BTStack stack;
102+
103+
Assert(IndexRelationGetNumberOfAttributes(rel) != 0);
104+
indnkeyatts = IndexRelationGetNumberOfKeyAttributes(rel);
105+
Assert(indnkeyatts != 0);
106+
107+
itup_scankey = _bt_mkscankey(rel, itup);
108+
109+
stack = _bt_search(rel, indnkeyatts, itup_scankey, false, &buf, BT_WRITE, NULL);
110+
111+
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
112+
LockBuffer(buf, BT_WRITE);
113+
114+
buf = _bt_moveright(rel, buf, indnkeyatts, itup_scankey, false,
115+
true, stack, BT_WRITE, NULL);
116+
117+
itemsz = IndexTupleDSize(*itup);
118+
itemsz = MAXALIGN(itemsz);
119+
120+
page = BufferGetPage(buf);
121+
122+
_bt_relbuf(rel, buf);
123+
124+
if (itemsz > BTMaxItemSize(page))
125+
return true;
126+
127+
return false;
128+
}
129+
88130
/*
89131
* _bt_doinsert() -- Handle insertion of a single index tuple in the tree.
90132
*

src/backend/access/nbtree/nbtree.c

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "access/relscan.h"
2323
#include "access/xlog.h"
2424
#include "access/ptrack.h"
25+
#include "executor/executor.h" /* for using CreateExecutorState */
2526
#include "catalog/index.h"
2627
#include "commands/vacuum.h"
2728
#include "pgstat.h"
@@ -116,6 +117,8 @@ static void btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
116117
BTCycleId cycleid);
117118
static void btvacuumpage(BTVacState *vstate, BlockNumber blkno,
118119
BlockNumber orig_blkno);
120+
static void bt_get_data_from_heap(Relation rel, Datum *values, bool *isnull,
121+
ItemPointer ht_ctid, Relation heapRel);
119122

120123

121124
/*
@@ -328,9 +331,27 @@ btinsert(Relation rel, Datum *values, bool *isnull,
328331
{
329332
bool result;
330333
IndexTuple itup;
334+
int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(rel);
335+
int indnatts = IndexRelationGetNumberOfAttributes(rel);
336+
TupleDesc tupleDescIndex = RelationGetDescr(rel);
337+
bool data_too_long_for_making_a_tup = true;
338+
339+
340+
/* Forming an index tuple from the values[] and isnull[] arrays */
341+
itup = index_form_tuple_extended(tupleDescIndex, values, isnull, indnkeyatts, &data_too_long_for_making_a_tup);
342+
343+
/* If we discovered that there's an INCLUDED attribute, AND that the data is too big to fit
344+
* in the index, we will take the data for building right from the heap. We do it because this
345+
* way we can get actual TOAST links rather than detoasted data. We want TOAST links becacuse we
346+
* might want to let INCLUDED attributes stay toasted when being put into the index.
347+
*/
348+
if((indnatts != indnkeyatts) && (data_too_long_for_making_a_tup || tuple_too_long_for_btree(rel, itup)) )
349+
{
350+
pfree(itup);
351+
bt_get_data_from_heap(rel, values, isnull, ht_ctid, heapRel);
352+
itup = index_form_tuple_extended(tupleDescIndex, values, isnull, indnkeyatts, NULL);
353+
}
331354

332-
/* generate an index tuple */
333-
itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
334355
itup->t_tid = *ht_ctid;
335356

336357
result = _bt_doinsert(rel, itup, checkUnique, heapRel);
@@ -472,6 +493,51 @@ btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
472493
return ntids;
473494
}
474495

496+
/*
497+
* Taking the data for building an index tuple right from the heap.
498+
* We do it in case if detoasted data turned out to be too long, because
499+
* this way we can get actual TOAST links rather than detoasted data.
500+
* We need it only becacuse we might want to let INCLUDED
501+
* attributes stay toasted when being put into the index.
502+
*
503+
* It will form data for btree tuple and put it into values[] and isnull[]
504+
*/
505+
void
506+
bt_get_data_from_heap(Relation rel, Datum *values, bool *isnull,
507+
ItemPointer ht_ctid, Relation heapRel)
508+
{
509+
TupleDesc tupleDescHeap = RelationGetDescr(heapRel);
510+
HeapTupleData htup;
511+
Buffer buffer;
512+
513+
htup.t_self = *ht_ctid;
514+
515+
/* Getting the tuple that we want to form an index tuple with from the heap */
516+
if (!heap_fetch(heapRel, SnapshotAny, &htup, &buffer, false, NULL))
517+
elog(ERROR, "failed to fetch tuple dy tid while tring to insert a tuple into btree");
518+
else
519+
{
520+
EState *estate = CreateExecutorState();
521+
IndexInfo *indexInfo = BuildIndexInfo(rel);
522+
TupleTableSlot *slot;
523+
/*
524+
* We put the tuple taken from the heap into a slot,
525+
* and then FormIndexDatum takes the data from that slot
526+
* and fills the values[] and isnull[] arrays with the
527+
* appropriate values for the column(s) of the index.
528+
* IndexInfo explains the structure of the index tuple.
529+
*/
530+
slot = MakeSingleTupleTableSlot(tupleDescHeap);
531+
ExecStoreTuple(&htup, slot, InvalidBuffer, false);
532+
533+
FormIndexDatum(indexInfo, slot, estate,
534+
values, isnull);
535+
536+
ExecDropSingleTupleTableSlot(slot);
537+
ReleaseBuffer(buffer);
538+
}
539+
}
540+
475541
/*
476542
* btbeginscan() -- start a scan on a btree index
477543
*/

src/backend/utils/sort/tuplesort.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1411,8 +1411,10 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
14111411
SortTuple stup;
14121412
Datum original;
14131413
IndexTuple tuple;
1414+
int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(rel);
1415+
1416+
stup.tuple = index_form_tuple_extended(RelationGetDescr(rel), values, isnull, indnkeyatts, NULL);
14141417

1415-
stup.tuple = index_form_tuple(RelationGetDescr(rel), values, isnull);
14161418
tuple = ((IndexTuple) stup.tuple);
14171419
tuple->t_tid = *self;
14181420
USEMEM(state, GetMemoryChunkSpace(stup.tuple));

src/include/access/itup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ typedef IndexAttributeBitMapData * IndexAttributeBitMap;
143143
/* routines in indextuple.c */
144144
extern IndexTuple index_form_tuple(TupleDesc tupleDescriptor,
145145
Datum *values, bool *isnull);
146+
extern IndexTuple index_form_tuple_extended(TupleDesc tupleDescriptor,
147+
Datum *values, bool *isnull, int nkeyattrs, bool *sz_check_failed);
146148
extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
147149
TupleDesc tupleDesc);
148150
extern void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor,

src/include/access/nbtree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, int access);
473473
extern void _bt_finish_split(Relation rel, Buffer bbuf, BTStack stack);
474474
extern bool _bt_pgaddtup(Page page, Size itemsize, IndexTuple itup,
475475
OffsetNumber itup_off);
476+
extern bool tuple_too_long_for_btree(Relation rel, IndexTuple itup);
476477

477478
/*
478479
* prototypes for functions in nbtpage.c

0 commit comments

Comments
 (0)