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

Commit 9890857

Browse files
committed
Merge branch 'PGPRO10' into PGPROEE10
2 parents 8a3aa4b + 15d5f90 commit 9890857

File tree

13 files changed

+183
-13
lines changed

13 files changed

+183
-13
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
@@ -88,6 +88,48 @@ static bool _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
8888
static void _bt_vacuum_one_page(Relation rel, Buffer buffer, Relation heapRel);
8989

9090

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

src/backend/access/nbtree/nbtree.c

Lines changed: 66 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 "nodes/primnodes.h"
@@ -339,9 +340,27 @@ btinsert(Relation rel, Datum *values, bool *isnull,
339340
{
340341
bool result;
341342
IndexTuple itup;
343+
int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(rel);
344+
int indnatts = IndexRelationGetNumberOfAttributes(rel);
345+
TupleDesc tupleDescIndex = RelationGetDescr(rel);
346+
bool data_too_long_for_making_a_tup = true;
347+
348+
349+
/* Forming an index tuple from the values[] and isnull[] arrays */
350+
itup = index_form_tuple_extended(tupleDescIndex, values, isnull, indnkeyatts, &data_too_long_for_making_a_tup);
351+
352+
/* If we discovered that there's an INCLUDED attribute, AND that the data is too big to fit
353+
* in the index, we will take the data for building right from the heap. We do it because this
354+
* way we can get actual TOAST links rather than detoasted data. We want TOAST links becacuse we
355+
* might want to let INCLUDED attributes stay toasted when being put into the index.
356+
*/
357+
if((indnatts != indnkeyatts) && (data_too_long_for_making_a_tup || tuple_too_long_for_btree(rel, itup)) )
358+
{
359+
pfree(itup);
360+
bt_get_data_from_heap(rel, values, isnull, ht_ctid, heapRel);
361+
itup = index_form_tuple_extended(tupleDescIndex, values, isnull, indnkeyatts, NULL);
362+
}
342363

343-
/* generate an index tuple */
344-
itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
345364
itup->t_tid = *ht_ctid;
346365

347366
result = _bt_doinsert(rel, itup, checkUnique, heapRel);
@@ -493,6 +512,51 @@ btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
493512
return ntids;
494513
}
495514

515+
/*
516+
* Taking the data for building an index tuple right from the heap.
517+
* We do it in case if detoasted data turned out to be too long, because
518+
* this way we can get actual TOAST links rather than detoasted data.
519+
* We need it only becacuse we might want to let INCLUDED
520+
* attributes stay toasted when being put into the index.
521+
*
522+
* It will form data for btree tuple and put it into values[] and isnull[]
523+
*/
524+
void
525+
bt_get_data_from_heap(Relation rel, Datum *values, bool *isnull,
526+
ItemPointer ht_ctid, Relation heapRel)
527+
{
528+
TupleDesc tupleDescHeap = RelationGetDescr(heapRel);
529+
HeapTupleData htup;
530+
Buffer buffer;
531+
532+
htup.t_self = *ht_ctid;
533+
534+
/* Getting the tuple that we want to form an index tuple with from the heap */
535+
if (!heap_fetch(heapRel, SnapshotAny, &htup, &buffer, false, NULL))
536+
elog(ERROR, "failed to fetch tuple dy tid while tring to insert a tuple into btree");
537+
else
538+
{
539+
EState *estate = CreateExecutorState();
540+
IndexInfo *indexInfo = BuildIndexInfo(rel);
541+
TupleTableSlot *slot;
542+
/*
543+
* We put the tuple taken from the heap into a slot,
544+
* and then FormIndexDatum takes the data from that slot
545+
* and fills the values[] and isnull[] arrays with the
546+
* appropriate values for the column(s) of the index.
547+
* IndexInfo explains the structure of the index tuple.
548+
*/
549+
slot = MakeSingleTupleTableSlot(tupleDescHeap);
550+
ExecStoreTuple(&htup, slot, InvalidBuffer, false);
551+
552+
FormIndexDatum(indexInfo, slot, estate,
553+
values, isnull);
554+
555+
ExecDropSingleTupleTableSlot(slot);
556+
ReleaseBuffer(buffer);
557+
}
558+
}
559+
496560
/*
497561
* btbeginscan() -- start a scan on a btree index
498562
*/

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
@@ -142,6 +142,8 @@ typedef IndexAttributeBitMapData * IndexAttributeBitMap;
142142
/* routines in indextuple.c */
143143
extern IndexTuple index_form_tuple(TupleDesc tupleDescriptor,
144144
Datum *values, bool *isnull);
145+
extern IndexTuple index_form_tuple_extended(TupleDesc tupleDescriptor,
146+
Datum *values, bool *isnull, int nkeyattrs, bool *sz_check_failed);
145147
extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
146148
TupleDesc tupleDesc);
147149
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
@@ -542,6 +542,7 @@ extern void _bt_pgrewritetup(Relation rel, Buffer buf, Page page, OffsetNumber o
542542
extern bool _bt_isbinaryequal(TupleDesc itupdesc, IndexTuple itup, int nindatts, IndexTuple ituptoinsert);
543543
extern bool _bt_pgaddtup(Page page, Size itemsize, IndexTuple itup,
544544
OffsetNumber itup_off);
545+
extern bool tuple_too_long_for_btree(Relation rel, IndexTuple itup);
545546

546547
/*
547548
* prototypes for functions in nbtpage.c

0 commit comments

Comments
 (0)