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

Commit94d626f

Browse files
committed
Use materialize SRF mode in brin_page_items
This function was using the single-value-per-call mechanism, but thecode relied on a relcache entry that wasn't kept open across calls.This manifested as weird errors in buildfarm during the short time thatthe "brin-1" isolation test lived.Backpatch to 9.5, where it was introduced.
1 parent36e863b commit94d626f

File tree

1 file changed

+101
-122
lines changed

1 file changed

+101
-122
lines changed

‎contrib/pageinspect/brinfuncs.c

Lines changed: 101 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,6 @@ typedef struct brin_column_state
3737
FmgrInfooutputFn[FLEXIBLE_ARRAY_MEMBER];
3838
}brin_column_state;
3939

40-
typedefstructbrin_page_state
41-
{
42-
BrinDesc*bdesc;
43-
Pagepage;
44-
OffsetNumberoffset;
45-
boolunusedItem;
46-
booldone;
47-
AttrNumberattno;
48-
BrinMemTuple*dtup;
49-
brin_column_state*columns[FLEXIBLE_ARRAY_MEMBER];
50-
}brin_page_state;
51-
5240

5341
staticPageverify_brin_page(bytea*raw_page,uint16type,
5442
constchar*strtype);
@@ -119,89 +107,89 @@ verify_brin_page(bytea *raw_page, uint16 type, const char *strtype)
119107
Datum
120108
brin_page_items(PG_FUNCTION_ARGS)
121109
{
122-
brin_page_state*state;
123-
FuncCallContext*fctx;
110+
bytea*raw_page=PG_GETARG_BYTEA_P(0);
111+
OidindexRelid=PG_GETARG_OID(1);
112+
ReturnSetInfo*rsinfo= (ReturnSetInfo*)fcinfo->resultinfo;
113+
TupleDesctupdesc;
114+
MemoryContextoldcontext;
115+
Tuplestorestate*tupstore;
116+
RelationindexRel;
117+
brin_column_state**columns;
118+
BrinDesc*bdesc;
119+
BrinMemTuple*dtup;
120+
Pagepage;
121+
OffsetNumberoffset;
122+
AttrNumberattno;
123+
boolunusedItem;
124124

125125
if (!superuser())
126126
ereport(ERROR,
127127
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
128128
(errmsg("must be superuser to use raw page functions"))));
129129

130-
if (SRF_IS_FIRSTCALL())
131-
{
132-
bytea*raw_page=PG_GETARG_BYTEA_P(0);
133-
OidindexRelid=PG_GETARG_OID(1);
134-
Pagepage;
135-
TupleDesctupdesc;
136-
MemoryContextmctx;
137-
RelationindexRel;
138-
AttrNumberattno;
139-
140-
/* minimally verify the page we got */
141-
page=verify_brin_page(raw_page,BRIN_PAGETYPE_REGULAR,"regular");
130+
/* check to see if caller supports us returning a tuplestore */
131+
if (rsinfo==NULL|| !IsA(rsinfo,ReturnSetInfo))
132+
ereport(ERROR,
133+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
134+
errmsg("set-valued function called in context that cannot accept a set")));
135+
if (!(rsinfo->allowedModes&SFRM_Materialize)||
136+
rsinfo->expectedDesc==NULL)
137+
ereport(ERROR,
138+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
139+
errmsg("materialize mode required, but it is not allowed in this context")));
142140

143-
/* create a function context for cross-call persistence */
144-
fctx=SRF_FIRSTCALL_INIT();
141+
/* Build a tuple descriptor for our result type */
142+
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
143+
elog(ERROR,"return type must be a row type");
145144

146-
/*switchtomemory context appropriate for multiple function calls */
147-
mctx=MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
145+
/*Build tuplestoretohold the result rows */
146+
oldcontext=MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
148147

149-
/* Build a tuple descriptor for our result type */
150-
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
151-
elog(ERROR,"return type must be a row type");
148+
tupstore=tuplestore_begin_heap(true, false,work_mem);
149+
rsinfo->returnMode=SFRM_Materialize;
150+
rsinfo->setResult=tupstore;
151+
rsinfo->setDesc=tupdesc;
152152

153-
indexRel=index_open(indexRelid,AccessShareLock);
153+
MemoryContextSwitchTo(oldcontext);
154154

155-
state=palloc(offsetof(brin_page_state,columns)+
156-
sizeof(brin_column_state)*RelationGetDescr(indexRel)->natts);
155+
indexRel=index_open(indexRelid,AccessShareLock);
156+
bdesc=brin_build_desc(indexRel);
157157

158-
state->bdesc=brin_build_desc(indexRel);
159-
state->page=page;
160-
state->offset=FirstOffsetNumber;
161-
state->unusedItem= false;
162-
state->done= false;
163-
state->dtup=NULL;
158+
/* minimally verify the page we got */
159+
page=verify_brin_page(raw_page,BRIN_PAGETYPE_REGULAR,"regular");
164160

165-
/*
166-
* Initialize output functions for all indexed datatypes; simplifies
167-
* calling them later.
168-
*/
169-
for (attno=1;attno <=state->bdesc->bd_tupdesc->natts;attno++)
161+
/*
162+
* Initialize output functions for all indexed datatypes; simplifies
163+
* calling them later.
164+
*/
165+
columns=palloc(sizeof(brin_column_state*)*RelationGetDescr(indexRel)->natts);
166+
for (attno=1;attno <=bdesc->bd_tupdesc->natts;attno++)
167+
{
168+
Oidoutput;
169+
boolisVarlena;
170+
BrinOpcInfo*opcinfo;
171+
inti;
172+
brin_column_state*column;
173+
174+
opcinfo=bdesc->bd_info[attno-1];
175+
column=palloc(offsetof(brin_column_state,outputFn)+
176+
sizeof(FmgrInfo)*opcinfo->oi_nstored);
177+
178+
column->nstored=opcinfo->oi_nstored;
179+
for (i=0;i<opcinfo->oi_nstored;i++)
170180
{
171-
Oidoutput;
172-
boolisVarlena;
173-
BrinOpcInfo*opcinfo;
174-
inti;
175-
brin_column_state*column;
176-
177-
opcinfo=state->bdesc->bd_info[attno-1];
178-
column=palloc(offsetof(brin_column_state,outputFn)+
179-
sizeof(FmgrInfo)*opcinfo->oi_nstored);
180-
181-
column->nstored=opcinfo->oi_nstored;
182-
for (i=0;i<opcinfo->oi_nstored;i++)
183-
{
184-
getTypeOutputInfo(opcinfo->oi_typcache[i]->type_id,&output,&isVarlena);
185-
fmgr_info(output,&column->outputFn[i]);
186-
}
187-
188-
state->columns[attno-1]=column;
181+
getTypeOutputInfo(opcinfo->oi_typcache[i]->type_id,&output,&isVarlena);
182+
fmgr_info(output,&column->outputFn[i]);
189183
}
190184

191-
index_close(indexRel,AccessShareLock);
192-
193-
fctx->user_fctx=state;
194-
fctx->tuple_desc=BlessTupleDesc(tupdesc);
195-
196-
MemoryContextSwitchTo(mctx);
185+
columns[attno-1]=column;
197186
}
198187

199-
fctx=SRF_PERCALL_SETUP();
200-
state=fctx->user_fctx;
201-
202-
if (!state->done)
188+
offset=FirstOffsetNumber;
189+
unusedItem=false;
190+
dtup=NULL;
191+
for (;;)
203192
{
204-
HeapTupleresult;
205193
Datumvalues[7];
206194
boolnulls[7];
207195

@@ -211,39 +199,30 @@ brin_page_items(PG_FUNCTION_ARGS)
211199
* signal for obtaining and decoding the next one. If that's not the
212200
* case, we output the next attribute.
213201
*/
214-
if (state->dtup==NULL)
202+
if (dtup==NULL)
215203
{
216-
BrinTuple*tup;
217-
MemoryContextmctx;
218204
ItemIditemId;
219205

220-
/* deformed tuple must live across calls */
221-
mctx=MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
222-
223206
/* verify item status: if there's no data, we can't decode */
224-
itemId=PageGetItemId(state->page,state->offset);
207+
itemId=PageGetItemId(page,offset);
225208
if (ItemIdIsUsed(itemId))
226209
{
227-
tup= (BrinTuple*)PageGetItem(state->page,
228-
PageGetItemId(state->page,
229-
state->offset));
230-
state->dtup=brin_deform_tuple(state->bdesc,tup);
231-
state->attno=1;
232-
state->unusedItem= false;
210+
dtup=brin_deform_tuple(bdesc,
211+
(BrinTuple*)PageGetItem(page,itemId));
212+
attno=1;
213+
unusedItem= false;
233214
}
234215
else
235-
state->unusedItem= true;
236-
237-
MemoryContextSwitchTo(mctx);
216+
unusedItem= true;
238217
}
239218
else
240-
state->attno++;
219+
attno++;
241220

242221
MemSet(nulls,0,sizeof(nulls));
243222

244-
if (state->unusedItem)
223+
if (unusedItem)
245224
{
246-
values[0]=UInt16GetDatum(state->offset);
225+
values[0]=UInt16GetDatum(offset);
247226
nulls[1]= true;
248227
nulls[2]= true;
249228
nulls[3]= true;
@@ -253,17 +232,17 @@ brin_page_items(PG_FUNCTION_ARGS)
253232
}
254233
else
255234
{
256-
intatt=state->attno-1;
257-
258-
values[0]=UInt16GetDatum(state->offset);
259-
values[1]=UInt32GetDatum(state->dtup->bt_blkno);
260-
values[2]=UInt16GetDatum(state->attno);
261-
values[3]=BoolGetDatum(state->dtup->bt_columns[att].bv_allnulls);
262-
values[4]=BoolGetDatum(state->dtup->bt_columns[att].bv_hasnulls);
263-
values[5]=BoolGetDatum(state->dtup->bt_placeholder);
264-
if (!state->dtup->bt_columns[att].bv_allnulls)
235+
intatt=attno-1;
236+
237+
values[0]=UInt16GetDatum(offset);
238+
values[1]=UInt32GetDatum(dtup->bt_blkno);
239+
values[2]=UInt16GetDatum(attno);
240+
values[3]=BoolGetDatum(dtup->bt_columns[att].bv_allnulls);
241+
values[4]=BoolGetDatum(dtup->bt_columns[att].bv_hasnulls);
242+
values[5]=BoolGetDatum(dtup->bt_placeholder);
243+
if (!dtup->bt_columns[att].bv_allnulls)
265244
{
266-
BrinValues*bvalues=&state->dtup->bt_columns[att];
245+
BrinValues*bvalues=&dtup->bt_columns[att];
267246
StringInfoDatas;
268247
boolfirst;
269248
inti;
@@ -272,14 +251,14 @@ brin_page_items(PG_FUNCTION_ARGS)
272251
appendStringInfoChar(&s,'{');
273252

274253
first= true;
275-
for (i=0;i<state->columns[att]->nstored;i++)
254+
for (i=0;i<columns[att]->nstored;i++)
276255
{
277256
char*val;
278257

279258
if (!first)
280259
appendStringInfoString(&s," .. ");
281260
first= false;
282-
val=OutputFunctionCall(&state->columns[att]->outputFn[i],
261+
val=OutputFunctionCall(&columns[att]->outputFn[i],
283262
bvalues->bv_values[i]);
284263
appendStringInfoString(&s,val);
285264
pfree(val);
@@ -295,35 +274,35 @@ brin_page_items(PG_FUNCTION_ARGS)
295274
}
296275
}
297276

298-
result=heap_form_tuple(fctx->tuple_desc,values,nulls);
277+
tuplestore_putvalues(tupstore,tupdesc,values,nulls);
299278

300279
/*
301280
* If the item was unused, jump straight to the next one; otherwise,
302281
* the only cleanup needed here is to set our signal to go to the next
303282
* tuple in the following iteration, by freeing the current one.
304283
*/
305-
if (state->unusedItem)
306-
state->offset=OffsetNumberNext(state->offset);
307-
elseif (state->attno >=state->bdesc->bd_tupdesc->natts)
284+
if (unusedItem)
285+
offset=OffsetNumberNext(offset);
286+
elseif (attno >=bdesc->bd_tupdesc->natts)
308287
{
309-
pfree(state->dtup);
310-
state->dtup=NULL;
311-
state->offset=OffsetNumberNext(state->offset);
288+
pfree(dtup);
289+
dtup=NULL;
290+
offset=OffsetNumberNext(offset);
312291
}
313292

314293
/*
315-
* If we're beyond the end of the page, set flag to end the function
316-
* in the following iteration.
294+
* If we're beyond the end of the page, we're done.
317295
*/
318-
if (state->offset>PageGetMaxOffsetNumber(state->page))
319-
state->done= true;
320-
321-
SRF_RETURN_NEXT(fctx,HeapTupleGetDatum(result));
296+
if (offset>PageGetMaxOffsetNumber(page))
297+
break;
322298
}
323299

324-
brin_free_desc(state->bdesc);
300+
/* clean up and return the tuplestore */
301+
brin_free_desc(bdesc);
302+
tuplestore_donestoring(tupstore);
303+
index_close(indexRel,AccessShareLock);
325304

326-
SRF_RETURN_DONE(fctx);
305+
return (Datum)0;
327306
}
328307

329308
Datum

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp