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

Commit6fa7638

Browse files
author
Arthur Zakirov
committed
PGPRO-2601: Copy flattened HeapTuple
1 parent9319611 commit6fa7638

File tree

3 files changed

+142
-92
lines changed

3 files changed

+142
-92
lines changed

‎pg_variables.c‎

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ variable_select(PG_FUNCTION_ARGS)
606606
funcctx=SRF_FIRSTCALL_INIT();
607607
oldcontext=MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
608608

609-
funcctx->tuple_desc=CreateTupleDescCopy(record->tupdesc);
609+
funcctx->tuple_desc=record->tupdesc;
610610

611611
rstat= (HASH_SEQ_STATUS*)palloc0(sizeof(HASH_SEQ_STATUS));
612612
hash_seq_init(rstat,record->rhash);
@@ -626,11 +626,10 @@ variable_select(PG_FUNCTION_ARGS)
626626
item= (HashRecordEntry*)hash_seq_search(rstat);
627627
if (item!=NULL)
628628
{
629-
Datumresult;
630-
631-
result=HeapTupleGetDatum(item->tuple);
629+
Assert(!HeapTupleHeaderHasExternal(
630+
(HeapTupleHeader)DatumGetPointer(item->tuple)));
632631

633-
SRF_RETURN_NEXT(funcctx,result);
632+
SRF_RETURN_NEXT(funcctx,item->tuple);
634633
}
635634
else
636635
{
@@ -694,7 +693,12 @@ variable_select_by_value(PG_FUNCTION_ARGS)
694693
PG_FREE_IF_COPY(var_name,1);
695694

696695
if (found)
697-
PG_RETURN_DATUM(HeapTupleGetDatum(item->tuple));
696+
{
697+
Assert(!HeapTupleHeaderHasExternal(
698+
(HeapTupleHeader)DatumGetPointer(item->tuple)));
699+
700+
PG_RETURN_DATUM(item->tuple);
701+
}
698702
else
699703
PG_RETURN_NULL();
700704
}
@@ -751,7 +755,7 @@ variable_select_by_values(PG_FUNCTION_ARGS)
751755
funcctx=SRF_FIRSTCALL_INIT();
752756
oldcontext=MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
753757

754-
funcctx->tuple_desc=CreateTupleDescCopy(GetActualValue(variable).record.tupdesc);
758+
funcctx->tuple_desc=GetActualValue(variable).record.tupdesc;
755759

756760
var= (VariableIteratorRec*)palloc(sizeof(VariableIteratorRec));
757761
var->iterator=array_create_iterator(values,0,NULL);
@@ -784,11 +788,9 @@ variable_select_by_values(PG_FUNCTION_ARGS)
784788
HASH_FIND,&found);
785789
if (found)
786790
{
787-
Datumresult;
788-
789-
result=HeapTupleGetDatum(item->tuple);
790-
791-
SRF_RETURN_NEXT(funcctx,result);
791+
Assert(!HeapTupleHeaderHasExternal(
792+
(HeapTupleHeader)DatumGetPointer(item->tuple)));
793+
SRF_RETURN_NEXT(funcctx,item->tuple);
792794
}
793795
}
794796

@@ -1639,7 +1641,7 @@ copyValue(VarState *src, VarState *dest, Variable *destVar)
16391641
/* Copy previous history entry into the new one */
16401642
hash_seq_init(&rstat,record_src->rhash);
16411643
while ((item_src= (HashRecordEntry*)hash_seq_search(&rstat))!=NULL)
1642-
copy_record(record_dest,item_src->tuple,destVar);
1644+
insert_record_copy(record_dest,item_src->tuple,destVar);
16431645
}
16441646
else
16451647
/* copy scalar value */

‎pg_variables.h‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ typedef struct HashRecordKey
128128
typedefstructHashRecordEntry
129129
{
130130
HashRecordKeykey;
131-
HeapTupletuple;
131+
Datumtuple;
132132
}HashRecordEntry;
133133

134134
/* Element of list with objects created, changed or removed within transaction */
@@ -157,12 +157,12 @@ typedef struct ChangesStackNode
157157
externvoidinit_record(RecordVar*record,TupleDesctupdesc,Variable*variable);
158158
externvoidcheck_attributes(Variable*variable,TupleDesctupdesc);
159159
externvoidcheck_record_key(Variable*variable,Oidtypid);
160-
externvoidcopy_record(RecordVar*dest_record,HeapTuplesrc_tuple,
161-
Variable*variable);
162160

163161
externvoidinsert_record(Variable*variable,HeapTupleHeadertupleHeader);
164162
externboolupdate_record(Variable*variable,HeapTupleHeadertupleHeader);
165163
externbooldelete_record(Variable*variable,Datumvalue,boolis_null);
164+
externvoidinsert_record_copy(RecordVar*dest_record,Datumsrc_tuple,
165+
Variable*variable);
166166
externvoidremoveObject(TransObject*object,TransObjectTypetype);
167167

168168
#defineGetActualState(object) \

‎pg_variables_record.c‎

Lines changed: 124 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
*-------------------------------------------------------------------------
99
*/
1010
#include"postgres.h"
11+
#include"funcapi.h"
1112

1213
#include"access/htup_details.h"
14+
#include"access/tuptoaster.h"
1315
#include"catalog/pg_collation.h"
1416
#include"catalog/pg_type.h"
1517
#include"utils/builtins.h"
@@ -134,7 +136,11 @@ init_record(RecordVar *record, TupleDesc tupdesc, Variable *variable)
134136
#endif
135137

136138
oldcxt=MemoryContextSwitchTo(record->hctx);
137-
record->tupdesc=CreateTupleDescCopyConstr(tupdesc);
139+
record->tupdesc=CreateTupleDescCopy(tupdesc);
140+
record->tupdesc->tdhasoid= false;
141+
record->tupdesc->tdtypeid=RECORDOID;
142+
record->tupdesc->tdtypmod=-1;
143+
record->tupdesc=BlessTupleDesc(record->tupdesc);
138144

139145
/* Initialize hash table. */
140146
ctl.keysize=sizeof(HashRecordKey);
@@ -153,47 +159,6 @@ init_record(RecordVar *record, TupleDesc tupdesc, Variable *variable)
153159
MemoryContextSwitchTo(oldcxt);
154160
}
155161

156-
/*
157-
* Copy record using src_tuple.
158-
*/
159-
void
160-
copy_record(RecordVar*dest_record,HeapTuplesrc_tuple,Variable*variable)
161-
{
162-
HeapTupletuple;
163-
Datumvalue;
164-
boolisnull;
165-
HashRecordKeyk;
166-
HashRecordEntry*item;
167-
boolfound;
168-
MemoryContextoldcxt;
169-
170-
oldcxt=MemoryContextSwitchTo(dest_record->hctx);
171-
172-
/* Inserting a new record into dest_record */
173-
tuple=heap_copytuple(src_tuple);
174-
value=fastgetattr(tuple,1,dest_record->tupdesc,&isnull);
175-
176-
k.value=value;
177-
k.is_null=isnull;
178-
k.hash_proc=&dest_record->hash_proc;
179-
k.cmp_proc=&dest_record->cmp_proc;
180-
181-
item= (HashRecordEntry*)hash_search(dest_record->rhash,&k,
182-
HASH_ENTER,&found);
183-
if (found)
184-
{
185-
heap_freetuple(tuple);
186-
MemoryContextSwitchTo(oldcxt);
187-
ereport(ERROR,
188-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
189-
errmsg("there is a record in the variable \"%s\" with same "
190-
"key",GetName(variable))));
191-
}
192-
item->tuple=tuple;
193-
194-
MemoryContextSwitchTo(oldcxt);
195-
}
196-
197162
/*
198163
* New record structure should be the same as the first record.
199164
*/
@@ -247,15 +212,78 @@ check_record_key(Variable *variable, Oid typid)
247212
"key type",GetName(variable))));
248213
}
249214

215+
staticDatum
216+
copy_record_tuple(RecordVar*record,HeapTupleHeadertupleHeader)
217+
{
218+
TupleDesctupdesc;
219+
HeapTupleHeaderresult;
220+
inttuple_len;
221+
222+
tupdesc=record->tupdesc;
223+
224+
/*
225+
* If the tuple contains any external TOAST pointers, we have to inline
226+
* those fields to meet the conventions for composite-type Datums.
227+
*/
228+
if (HeapTupleHeaderHasExternal(tupleHeader))
229+
returntoast_flatten_tuple_to_datum(tupleHeader,
230+
HeapTupleHeaderGetDatumLength(tupleHeader),
231+
tupdesc);
232+
233+
/*
234+
* Fast path for easy case: just make a palloc'd copy and insert the
235+
* correct composite-Datum header fields (since those may not be set if
236+
* the given tuple came from disk, rather than from heap_form_tuple).
237+
*/
238+
tuple_len=HeapTupleHeaderGetDatumLength(tupleHeader);
239+
result= (HeapTupleHeader)palloc(tuple_len);
240+
memcpy((char*)result, (char*)tupleHeader,tuple_len);
241+
242+
HeapTupleHeaderSetDatumLength(result,tuple_len);
243+
HeapTupleHeaderSetTypeId(result,tupdesc->tdtypeid);
244+
HeapTupleHeaderSetTypMod(result,tupdesc->tdtypmod);
245+
246+
returnPointerGetDatum(result);
247+
}
248+
249+
staticDatum
250+
get_record_key(Datumtuple,TupleDesctupdesc,bool*isnull)
251+
{
252+
HeapTupleHeaderth= (HeapTupleHeader)DatumGetPointer(tuple);
253+
boolhasnulls=th->t_infomask&HEAP_HASNULL;
254+
bits8*bp=th->t_bits;/* ptr to null bitmap in tuple */
255+
char*tp;/* ptr to tuple data */
256+
longoff;/* offset in tuple data */
257+
intkeyatt=0;
258+
Form_pg_attributeattr=GetTupleDescAttr(tupdesc,keyatt);
259+
260+
if (hasnulls&&att_isnull(keyatt,bp))
261+
{
262+
*isnull= true;
263+
return (Datum)NULL;
264+
}
265+
266+
tp= (char*)th+th->t_hoff;
267+
off=0;
268+
if (attr->attlen==-1)
269+
off=att_align_pointer(off,attr->attalign,-1,tp+off);
270+
else
271+
{
272+
/* not varlena, so safe to use att_align_nominal */
273+
off=att_align_nominal(off,attr->attalign);
274+
}
275+
276+
*isnull= false;
277+
returnfetchatt(attr,tp+off);
278+
}
279+
250280
/*
251281
* Insert a new record. New record key should be unique in the variable.
252282
*/
253283
void
254284
insert_record(Variable*variable,HeapTupleHeadertupleHeader)
255285
{
256-
TupleDesctupdesc;
257-
HeapTupletuple;
258-
inttuple_len;
286+
Datumtuple;
259287
Datumvalue;
260288
boolisnull;
261289
RecordVar*record;
@@ -270,20 +298,10 @@ insert_record(Variable *variable, HeapTupleHeader tupleHeader)
270298

271299
oldcxt=MemoryContextSwitchTo(record->hctx);
272300

273-
tupdesc=record->tupdesc;
274-
275-
/* Build a HeapTuple control structure */
276-
tuple_len=HeapTupleHeaderGetDatumLength(tupleHeader);
277-
278-
tuple= (HeapTuple)palloc(HEAPTUPLESIZE+tuple_len);
279-
tuple->t_len=tuple_len;
280-
ItemPointerSetInvalid(&(tuple->t_self));
281-
tuple->t_tableOid=InvalidOid;
282-
tuple->t_data= (HeapTupleHeader) ((char*)tuple+HEAPTUPLESIZE);
283-
memcpy((char*)tuple->t_data, (char*)tupleHeader,tuple_len);
301+
tuple=copy_record_tuple(record,tupleHeader);
284302

285303
/* Inserting a new record */
286-
value=fastgetattr(tuple,1,tupdesc,&isnull);
304+
value=get_record_key(tuple,record->tupdesc,&isnull);
287305
/* First, check if there is a record with same key */
288306
k.value=value;
289307
k.is_null=isnull;
@@ -294,7 +312,7 @@ insert_record(Variable *variable, HeapTupleHeader tupleHeader)
294312
HASH_ENTER,&found);
295313
if (found)
296314
{
297-
heap_freetuple(tuple);
315+
pfree(DatumGetPointer(tuple));
298316
MemoryContextSwitchTo(oldcxt);
299317
ereport(ERROR,
300318
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -313,9 +331,7 @@ insert_record(Variable *variable, HeapTupleHeader tupleHeader)
313331
bool
314332
update_record(Variable*variable,HeapTupleHeadertupleHeader)
315333
{
316-
TupleDesctupdesc;
317-
HeapTupletuple;
318-
inttuple_len;
334+
Datumtuple;
319335
Datumvalue;
320336
boolisnull;
321337
RecordVar*record;
@@ -330,20 +346,10 @@ update_record(Variable *variable, HeapTupleHeader tupleHeader)
330346

331347
oldcxt=MemoryContextSwitchTo(record->hctx);
332348

333-
tupdesc=record->tupdesc;
334-
335-
/* Build a HeapTuple control structure */
336-
tuple_len=HeapTupleHeaderGetDatumLength(tupleHeader);
337-
338-
tuple= (HeapTuple)palloc(HEAPTUPLESIZE+tuple_len);
339-
tuple->t_len=tuple_len;
340-
ItemPointerSetInvalid(&(tuple->t_self));
341-
tuple->t_tableOid=InvalidOid;
342-
tuple->t_data= (HeapTupleHeader) ((char*)tuple+HEAPTUPLESIZE);
343-
memcpy((char*)tuple->t_data, (char*)tupleHeader,tuple_len);
349+
tuple=copy_record_tuple(record,tupleHeader);
344350

345351
/* Update a record */
346-
value=fastgetattr(tuple,1,tupdesc,&isnull);
352+
value=get_record_key(tuple,record->tupdesc,&isnull);
347353
k.value=value;
348354
k.is_null=isnull;
349355
k.hash_proc=&record->hash_proc;
@@ -353,13 +359,13 @@ update_record(Variable *variable, HeapTupleHeader tupleHeader)
353359
HASH_FIND,&found);
354360
if (!found)
355361
{
356-
heap_freetuple(tuple);
362+
pfree(DatumGetPointer(tuple));
357363
MemoryContextSwitchTo(oldcxt);
358364
return false;
359365
}
360366

361367
/* Release old tuple */
362-
heap_freetuple(item->tuple);
368+
pfree(DatumGetPointer(item->tuple));
363369
item->tuple=tuple;
364370

365371
MemoryContextSwitchTo(oldcxt);
@@ -387,7 +393,49 @@ delete_record(Variable *variable, Datum value, bool is_null)
387393
item= (HashRecordEntry*)hash_search(record->rhash,&k,
388394
HASH_REMOVE,&found);
389395
if (found)
390-
heap_freetuple(item->tuple);
396+
pfree(DatumGetPointer(item->tuple));
391397

392398
returnfound;
393399
}
400+
401+
/*
402+
* Copy record using src_tuple.
403+
*/
404+
void
405+
insert_record_copy(RecordVar*dest_record,Datumsrc_tuple,Variable*variable)
406+
{
407+
Datumtuple;
408+
Datumvalue;
409+
boolisnull;
410+
HashRecordKeyk;
411+
HashRecordEntry*item;
412+
boolfound;
413+
MemoryContextoldcxt;
414+
415+
oldcxt=MemoryContextSwitchTo(dest_record->hctx);
416+
417+
/* Inserting a new record into dest_record */
418+
tuple=copy_record_tuple(dest_record,
419+
(HeapTupleHeader)DatumGetPointer(src_tuple));
420+
value=get_record_key(tuple,dest_record->tupdesc,&isnull);
421+
422+
k.value=value;
423+
k.is_null=isnull;
424+
k.hash_proc=&dest_record->hash_proc;
425+
k.cmp_proc=&dest_record->cmp_proc;
426+
427+
item= (HashRecordEntry*)hash_search(dest_record->rhash,&k,
428+
HASH_ENTER,&found);
429+
if (found)
430+
{
431+
pfree(DatumGetPointer(tuple));
432+
MemoryContextSwitchTo(oldcxt);
433+
ereport(ERROR,
434+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
435+
errmsg("there is a record in the variable \"%s\" with same "
436+
"key",GetName(variable))));
437+
}
438+
item->tuple=tuple;
439+
440+
MemoryContextSwitchTo(oldcxt);
441+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2026 Movatter.jp