Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit40314f2

Browse files
committed
Modify tuptoaster's API so that it does not try to modify the passed
tuple in-place, but instead passes back an all-new tuple structure ifany changes are needed. This is a much cleaner and more robust solutionfor the bug discovered by Alexey Beschiokov; accordingly, revert thequick hack I installed yesterday.With this change, HeapTupleData.t_datamcxt is no longer needed; willremove it in a separate commit in HEAD only.
1 parent33a9af7 commit40314f2

File tree

4 files changed

+124
-101
lines changed

4 files changed

+124
-101
lines changed

‎src/backend/access/heap/heapam.c

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.200 2005/10/15 02:49:08 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.201 2005/11/20 18:38:20 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1085,12 +1085,19 @@ heap_get_latest_tid(Relation relation,
10851085
*
10861086
* use_fsm is passed directly to RelationGetBufferForTuple, which see for
10871087
* more info.
1088+
*
1089+
* The return value is the OID assigned to the tuple (either here or by the
1090+
* caller), or InvalidOid if no OID. The header fields of *tup are updated
1091+
* to match the stored tuple; in particular tup->t_self receives the actual
1092+
* TID where the tuple was stored. But note that any toasting of fields
1093+
* within the tuple data is NOT reflected into *tup.
10881094
*/
10891095
Oid
10901096
heap_insert(Relationrelation,HeapTupletup,CommandIdcid,
10911097
booluse_wal,booluse_fsm)
10921098
{
10931099
TransactionIdxid=GetCurrentTransactionId();
1100+
HeapTupleheaptup;
10941101
Bufferbuffer;
10951102

10961103
if (relation->rd_rel->relhasoids)
@@ -1128,19 +1135,24 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
11281135
/*
11291136
* If the new tuple is too big for storage or contains already toasted
11301137
* out-of-line attributes from some other relation, invoke the toaster.
1138+
*
1139+
* Note: below this point, heaptup is the data we actually intend to
1140+
* store into the relation; tup is the caller's original untoasted data.
11311141
*/
11321142
if (HeapTupleHasExternal(tup)||
11331143
(MAXALIGN(tup->t_len)>TOAST_TUPLE_THRESHOLD))
1134-
heap_tuple_toast_attrs(relation,tup,NULL);
1144+
heaptup=toast_insert_or_update(relation,tup,NULL);
1145+
else
1146+
heaptup=tup;
11351147

11361148
/* Find buffer to insert this tuple into */
1137-
buffer=RelationGetBufferForTuple(relation,tup->t_len,
1149+
buffer=RelationGetBufferForTuple(relation,heaptup->t_len,
11381150
InvalidBuffer,use_fsm);
11391151

11401152
/* NO EREPORT(ERROR) from here till changes are logged */
11411153
START_CRIT_SECTION();
11421154

1143-
RelationPutHeapTuple(relation,buffer,tup);
1155+
RelationPutHeapTuple(relation,buffer,heaptup);
11441156

11451157
/* XLOG stuff */
11461158
if (relation->rd_istemp)
@@ -1158,15 +1170,15 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
11581170
uint8info=XLOG_HEAP_INSERT;
11591171

11601172
xlrec.target.node=relation->rd_node;
1161-
xlrec.target.tid=tup->t_self;
1173+
xlrec.target.tid=heaptup->t_self;
11621174
rdata[0].data= (char*)&xlrec;
11631175
rdata[0].len=SizeOfHeapInsert;
11641176
rdata[0].buffer=InvalidBuffer;
11651177
rdata[0].next=&(rdata[1]);
11661178

1167-
xlhdr.t_natts=tup->t_data->t_natts;
1168-
xlhdr.t_infomask=tup->t_data->t_infomask;
1169-
xlhdr.t_hoff=tup->t_data->t_hoff;
1179+
xlhdr.t_natts=heaptup->t_data->t_natts;
1180+
xlhdr.t_infomask=heaptup->t_data->t_infomask;
1181+
xlhdr.t_hoff=heaptup->t_data->t_hoff;
11701182

11711183
/*
11721184
* note we mark rdata[1] as belonging to buffer; if XLogInsert decides
@@ -1180,8 +1192,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
11801192
rdata[1].next=&(rdata[2]);
11811193

11821194
/* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
1183-
rdata[2].data= (char*)tup->t_data+ offsetof(HeapTupleHeaderData,t_bits);
1184-
rdata[2].len=tup->t_len- offsetof(HeapTupleHeaderData,t_bits);
1195+
rdata[2].data= (char*)heaptup->t_data+ offsetof(HeapTupleHeaderData,t_bits);
1196+
rdata[2].len=heaptup->t_len- offsetof(HeapTupleHeaderData,t_bits);
11851197
rdata[2].buffer=buffer;
11861198
rdata[2].buffer_std= true;
11871199
rdata[2].next=NULL;
@@ -1191,7 +1203,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
11911203
* page instead of restoring the whole thing. Set flag, and hide
11921204
* buffer references from XLogInsert.
11931205
*/
1194-
if (ItemPointerGetOffsetNumber(&(tup->t_self))==FirstOffsetNumber&&
1206+
if (ItemPointerGetOffsetNumber(&(heaptup->t_self))==FirstOffsetNumber&&
11951207
PageGetMaxOffsetNumber(page)==FirstOffsetNumber)
11961208
{
11971209
info |=XLOG_HEAP_INIT_PAGE;
@@ -1212,13 +1224,23 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
12121224
/*
12131225
* If tuple is cachable, mark it for invalidation from the caches in case
12141226
* we abort. Note it is OK to do this after WriteBuffer releases the
1215-
* buffer, because the"tup" data structure is all in local memory, not in
1216-
* the shared buffer.
1227+
* buffer, because theheaptup data structure is all in local memory,
1228+
*not inthe shared buffer.
12171229
*/
1218-
CacheInvalidateHeapTuple(relation,tup);
1230+
CacheInvalidateHeapTuple(relation,heaptup);
12191231

12201232
pgstat_count_heap_insert(&relation->pgstat_info);
12211233

1234+
/*
1235+
* If heaptup is a private copy, release it. Don't forget to copy t_self
1236+
* back to the caller's image, too.
1237+
*/
1238+
if (heaptup!=tup)
1239+
{
1240+
tup->t_self=heaptup->t_self;
1241+
heap_freetuple(heaptup);
1242+
}
1243+
12221244
returnHeapTupleGetOid(tup);
12231245
}
12241246

@@ -1469,7 +1491,7 @@ heap_delete(Relation relation, ItemPointer tid,
14691491
* context lock on the buffer first.
14701492
*/
14711493
if (HeapTupleHasExternal(&tp))
1472-
heap_tuple_toast_attrs(relation,NULL,&tp);
1494+
toast_delete(relation,&tp);
14731495

14741496
/*
14751497
* Mark tuple for invalidation from system caches at next command
@@ -1553,8 +1575,10 @@ simple_heap_delete(Relation relation, ItemPointer tid)
15531575
* HeapTupleSelfUpdated, HeapTupleUpdated, or HeapTupleBeingUpdated
15541576
* (the last only possible if wait == false).
15551577
*
1556-
* On success, newtup->t_self is set to the TID where the new tuple
1557-
* was inserted.
1578+
* On success, the header fields of *newtup are updated to match the new
1579+
* stored tuple; in particular, newtup->t_self is set to the TID where the
1580+
* new tuple was inserted. However, any TOAST changes in the new tuple's
1581+
* data are not reflected into *newtup.
15581582
*
15591583
* In the failure cases, the routine returns the tuple's t_ctid and t_xmax.
15601584
* If t_ctid is the same as otid, the tuple was deleted; if different, the
@@ -1570,6 +1594,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
15701594
TransactionIdxid=GetCurrentTransactionId();
15711595
ItemIdlp;
15721596
HeapTupleDataoldtup;
1597+
HeapTupleheaptup;
15731598
PageHeaderdp;
15741599
Bufferbuffer,
15751600
newbuf;
@@ -1760,11 +1785,12 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
17601785
* We need to invoke the toaster if there are already any out-of-line toasted
17611786
* values present, or if the new tuple is over-threshold.
17621787
*/
1788+
newtupsize=MAXALIGN(newtup->t_len);
1789+
17631790
need_toast= (HeapTupleHasExternal(&oldtup)||
17641791
HeapTupleHasExternal(newtup)||
1765-
(MAXALIGN(newtup->t_len)>TOAST_TUPLE_THRESHOLD));
1792+
newtupsize>TOAST_TUPLE_THRESHOLD);
17661793

1767-
newtupsize=MAXALIGN(newtup->t_len);
17681794
pagefree=PageGetFreeSpace((Page)dp);
17691795

17701796
if (need_toast||newtupsize>pagefree)
@@ -1776,15 +1802,25 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
17761802
HEAP_MOVED);
17771803
HeapTupleHeaderSetXmax(oldtup.t_data,xid);
17781804
HeapTupleHeaderSetCmax(oldtup.t_data,cid);
1805+
/* temporarily make it look not-updated */
1806+
oldtup.t_data->t_ctid=oldtup.t_self;
17791807
already_marked= true;
17801808
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
17811809

1782-
/* Let the toaster do its thing */
1810+
/*
1811+
* Let the toaster do its thing, if needed.
1812+
*
1813+
* Note: below this point, heaptup is the data we actually intend to
1814+
* store into the relation; newtup is the caller's original untoasted
1815+
* data.
1816+
*/
17831817
if (need_toast)
17841818
{
1785-
heap_tuple_toast_attrs(relation,newtup,&oldtup);
1786-
newtupsize=MAXALIGN(newtup->t_len);
1819+
heaptup=toast_insert_or_update(relation,newtup,&oldtup);
1820+
newtupsize=MAXALIGN(heaptup->t_len);
17871821
}
1822+
else
1823+
heaptup=newtup;
17881824

17891825
/*
17901826
* Now, do we need a new page for the tuple, or not? This is a bit
@@ -1805,8 +1841,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
18051841
*/
18061842
if (newtupsize>pagefree)
18071843
{
1808-
/* Assume there's no chance to putnewtup on same page. */
1809-
newbuf=RelationGetBufferForTuple(relation,newtup->t_len,
1844+
/* Assume there's no chance to putheaptup on same page. */
1845+
newbuf=RelationGetBufferForTuple(relation,heaptup->t_len,
18101846
buffer, true);
18111847
}
18121848
else
@@ -1823,7 +1859,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
18231859
* seldom be taken.
18241860
*/
18251861
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
1826-
newbuf=RelationGetBufferForTuple(relation,newtup->t_len,
1862+
newbuf=RelationGetBufferForTuple(relation,heaptup->t_len,
18271863
buffer, true);
18281864
}
18291865
else
@@ -1838,6 +1874,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
18381874
/* No TOAST work needed, and it'll fit on same page */
18391875
already_marked= false;
18401876
newbuf=buffer;
1877+
heaptup=newtup;
18411878
}
18421879

18431880
/*
@@ -1849,7 +1886,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
18491886
/* NO EREPORT(ERROR) from here till changes are logged */
18501887
START_CRIT_SECTION();
18511888

1852-
RelationPutHeapTuple(relation,newbuf,newtup);/* insert new tuple */
1889+
RelationPutHeapTuple(relation,newbuf,heaptup);/* insert new tuple */
18531890

18541891
if (!already_marked)
18551892
{
@@ -1863,13 +1900,13 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
18631900
}
18641901

18651902
/* record address of new tuple in t_ctid of old one */
1866-
oldtup.t_data->t_ctid=newtup->t_self;
1903+
oldtup.t_data->t_ctid=heaptup->t_self;
18671904

18681905
/* XLOG stuff */
18691906
if (!relation->rd_istemp)
18701907
{
18711908
XLogRecPtrrecptr=log_heap_update(relation,buffer,oldtup.t_self,
1872-
newbuf,newtup, false);
1909+
newbuf,heaptup, false);
18731910

18741911
if (newbuf!=buffer)
18751912
{
@@ -1905,10 +1942,10 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
19051942
/*
19061943
* If new tuple is cachable, mark it for invalidation from the caches in
19071944
* case we abort. Note it is OK to do this after WriteBuffer releases the
1908-
* buffer, because the"newtup" data structure is all in local memory, not
1945+
* buffer, because theheaptup data structure is all in local memory, not
19091946
* in the shared buffer.
19101947
*/
1911-
CacheInvalidateHeapTuple(relation,newtup);
1948+
CacheInvalidateHeapTuple(relation,heaptup);
19121949

19131950
/*
19141951
* Release the lmgr tuple lock, if we had it.
@@ -1918,6 +1955,16 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
19181955

19191956
pgstat_count_heap_update(&relation->pgstat_info);
19201957

1958+
/*
1959+
* If heaptup is a private copy, release it. Don't forget to copy t_self
1960+
* back to the caller's image, too.
1961+
*/
1962+
if (heaptup!=newtup)
1963+
{
1964+
newtup->t_self=heaptup->t_self;
1965+
heap_freetuple(heaptup);
1966+
}
1967+
19211968
returnHeapTupleMayBeUpdated;
19221969
}
19231970

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp