@@ -92,65 +92,56 @@ gist_page_opaque_info(PG_FUNCTION_ARGS)
9292 return HeapTupleGetDatum (resultTuple );
9393}
9494
95- typedef struct gist_page_items_state
96- {
97- Page page ;
98- TupleDesc tupd ;
99- OffsetNumber offset ;
100- Relation rel ;
101- } gist_page_items_state ;
102-
10395Datum
10496gist_page_items_bytea (PG_FUNCTION_ARGS )
10597{
10698 bytea * raw_page = PG_GETARG_BYTEA_P (0 );
107- FuncCallContext * fctx ;
108- gist_page_items_state * inter_call_data ;
99+ ReturnSetInfo * rsinfo = (ReturnSetInfo * ) fcinfo -> resultinfo ;
100+ bool randomAccess ;
101+ TupleDesc tupdesc ;
102+ Tuplestorestate * tupstore ;
103+ MemoryContext oldcontext ;
104+ Page page ;
105+ OffsetNumber offset ;
109106
110107 if (!superuser ())
111108 ereport (ERROR ,
112109 (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
113110 errmsg ("must be superuser to use raw page functions" )));
114111
115- if (SRF_IS_FIRSTCALL ())
116- {
117- TupleDesc tupdesc ;
118- MemoryContext mctx ;
119- Page page ;
120-
121- fctx = SRF_FIRSTCALL_INIT ();
122- mctx = MemoryContextSwitchTo (fctx -> multi_call_memory_ctx );
123-
124- page = get_page_from_raw (raw_page );
125-
126- inter_call_data = palloc (sizeof (gist_page_items_state ));
112+ /* check to see if caller supports us returning a tuplestore */
113+ if (rsinfo == NULL || !IsA (rsinfo , ReturnSetInfo ))
114+ ereport (ERROR ,
115+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
116+ errmsg ("set-valued function called in context that cannot accept a set" )));
117+ if (!(rsinfo -> allowedModes & SFRM_Materialize ))
118+ ereport (ERROR ,
119+ (errcode (ERRCODE_SYNTAX_ERROR ),
120+ errmsg ("materialize mode required, but it is not allowed in this context" )));
127121
128- /* Build a tuple descriptor for our result type */
129- if (get_call_result_type (fcinfo , NULL , & tupdesc ) != TYPEFUNC_COMPOSITE )
130- elog (ERROR , "return type must be a row type" );
122+ /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
123+ oldcontext = MemoryContextSwitchTo (rsinfo -> econtext -> ecxt_per_query_memory );
131124
132- if (GistPageIsDeleted ( page ) )
133- elog (NOTICE , "page is deleted " );
125+ if (get_call_result_type ( fcinfo , NULL , & tupdesc ) != TYPEFUNC_COMPOSITE )
126+ elog (ERROR , "return type must be a row type " );
134127
135- inter_call_data -> page = page ;
136- inter_call_data -> tupd = tupdesc ;
137- inter_call_data -> offset = FirstOffsetNumber ;
128+ randomAccess = (rsinfo -> allowedModes & SFRM_Materialize_Random ) != 0 ;
129+ tupstore = tuplestore_begin_heap (randomAccess , false, work_mem );
130+ rsinfo -> returnMode = SFRM_Materialize ;
131+ rsinfo -> setResult = tupstore ;
132+ rsinfo -> setDesc = tupdesc ;
138133
139- fctx -> max_calls = PageGetMaxOffsetNumber (page );
140- fctx -> user_fctx = inter_call_data ;
134+ MemoryContextSwitchTo (oldcontext );
141135
142- MemoryContextSwitchTo (mctx );
143- }
136+ page = get_page_from_raw (raw_page );
144137
145- fctx = SRF_PERCALL_SETUP ();
146- inter_call_data = fctx -> user_fctx ;
138+ if ( GistPageIsDeleted ( page ))
139+ elog ( NOTICE , "page is deleted" ) ;
147140
148- if (fctx -> call_cntr < fctx -> max_calls )
141+ for (offset = FirstOffsetNumber ;
142+ offset <= PageGetMaxOffsetNumber (page );
143+ offset ++ )
149144 {
150- Page page = inter_call_data -> page ;
151- OffsetNumber offset = inter_call_data -> offset ;
152- HeapTuple resultTuple ;
153- Datum result ;
154145 Datum values [4 ];
155146 bool nulls [4 ];
156147 ItemId id ;
@@ -177,74 +168,67 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
177168 memcpy (VARDATA (tuple_bytea ), itup , tuple_len );
178169 values [3 ] = PointerGetDatum (tuple_bytea );
179170
180- /* Build and return the result tuple. */
181- resultTuple = heap_form_tuple (inter_call_data -> tupd , values , nulls );
182- result = HeapTupleGetDatum (resultTuple );
183-
184- inter_call_data -> offset ++ ;
185- SRF_RETURN_NEXT (fctx , result );
171+ tuplestore_putvalues (tupstore , tupdesc , values , nulls );
186172 }
187173
188- SRF_RETURN_DONE ( fctx ) ;
174+ return ( Datum ) 0 ;
189175}
190176
191177Datum
192178gist_page_items (PG_FUNCTION_ARGS )
193179{
194180 bytea * raw_page = PG_GETARG_BYTEA_P (0 );
195181 Oid indexRelid = PG_GETARG_OID (1 );
196- FuncCallContext * fctx ;
197- gist_page_items_state * inter_call_data ;
182+ ReturnSetInfo * rsinfo = (ReturnSetInfo * ) fcinfo -> resultinfo ;
183+ bool randomAccess ;
184+ Relation indexRel ;
185+ TupleDesc tupdesc ;
186+ Tuplestorestate * tupstore ;
187+ MemoryContext oldcontext ;
188+ Page page ;
189+ OffsetNumber offset ;
198190
199191 if (!superuser ())
200192 ereport (ERROR ,
201193 (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
202194 errmsg ("must be superuser to use raw page functions" )));
203195
204- if (SRF_IS_FIRSTCALL ())
205- {
206- Relation indexRel ;
207- TupleDesc tupdesc ;
208- MemoryContext mctx ;
209- Page page ;
210-
211- fctx = SRF_FIRSTCALL_INIT ();
212- mctx = MemoryContextSwitchTo (fctx -> multi_call_memory_ctx );
213-
214- page = get_page_from_raw (raw_page );
215-
216- inter_call_data = palloc (sizeof (gist_page_items_state ));
196+ /* check to see if caller supports us returning a tuplestore */
197+ if (rsinfo == NULL || !IsA (rsinfo , ReturnSetInfo ))
198+ ereport (ERROR ,
199+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
200+ errmsg ("set-valued function called in context that cannot accept a set" )));
201+ if (!(rsinfo -> allowedModes & SFRM_Materialize ))
202+ ereport (ERROR ,
203+ (errcode (ERRCODE_SYNTAX_ERROR ),
204+ errmsg ("materialize mode required, but it is not allowed in this context" )));
217205
218- /* Open the relation */
219- indexRel = index_open ( indexRelid , AccessShareLock );
206+ /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
207+ oldcontext = MemoryContextSwitchTo ( rsinfo -> econtext -> ecxt_per_query_memory );
220208
221- /* Build a tuple descriptor for our result type */
222- if (get_call_result_type (fcinfo , NULL , & tupdesc ) != TYPEFUNC_COMPOSITE )
223- elog (ERROR , "return type must be a row type" );
209+ if (get_call_result_type (fcinfo , NULL , & tupdesc ) != TYPEFUNC_COMPOSITE )
210+ elog (ERROR , "return type must be a row type" );
224211
225- if (GistPageIsDeleted (page ))
226- elog (NOTICE , "page is deleted" );
212+ randomAccess = (rsinfo -> allowedModes & SFRM_Materialize_Random ) != 0 ;
213+ tupstore = tuplestore_begin_heap (randomAccess , false, work_mem );
214+ rsinfo -> returnMode = SFRM_Materialize ;
215+ rsinfo -> setResult = tupstore ;
216+ rsinfo -> setDesc = tupdesc ;
227217
228- inter_call_data -> page = page ;
229- inter_call_data -> tupd = tupdesc ;
230- inter_call_data -> offset = FirstOffsetNumber ;
231- inter_call_data -> rel = indexRel ;
218+ MemoryContextSwitchTo (oldcontext );
232219
233- fctx -> max_calls = PageGetMaxOffsetNumber ( page );
234- fctx -> user_fctx = inter_call_data ;
220+ /* Open the relation */
221+ indexRel = index_open ( indexRelid , AccessShareLock ) ;
235222
236- MemoryContextSwitchTo (mctx );
237- }
223+ page = get_page_from_raw (raw_page );
238224
239- fctx = SRF_PERCALL_SETUP ();
240- inter_call_data = fctx -> user_fctx ;
225+ if ( GistPageIsDeleted ( page ))
226+ elog ( NOTICE , "page is deleted" ) ;
241227
242- if (fctx -> call_cntr < fctx -> max_calls )
228+ for (offset = FirstOffsetNumber ;
229+ offset <= PageGetMaxOffsetNumber (page );
230+ offset ++ )
243231 {
244- Page page = inter_call_data -> page ;
245- OffsetNumber offset = inter_call_data -> offset ;
246- HeapTuple resultTuple ;
247- Datum result ;
248232 Datum values [4 ];
249233 bool nulls [4 ];
250234 ItemId id ;
@@ -260,11 +244,10 @@ gist_page_items(PG_FUNCTION_ARGS)
260244
261245 itup = (IndexTuple ) PageGetItem (page , id );
262246
263- index_deform_tuple (itup , RelationGetDescr (inter_call_data -> rel ),
247+ index_deform_tuple (itup , RelationGetDescr (indexRel ),
264248 itup_values , itup_isnull );
265249
266- key_desc = BuildIndexValueDescription (inter_call_data -> rel , itup_values ,
267- itup_isnull );
250+ key_desc = BuildIndexValueDescription (indexRel , itup_values , itup_isnull );
268251
269252 memset (nulls , 0 , sizeof (nulls ));
270253
@@ -273,15 +256,10 @@ gist_page_items(PG_FUNCTION_ARGS)
273256 values [2 ] = Int32GetDatum ((int ) IndexTupleSize (itup ));
274257 values [3 ] = CStringGetTextDatum (key_desc );
275258
276- /* Build and return the result tuple. */
277- resultTuple = heap_form_tuple (inter_call_data -> tupd , values , nulls );
278- result = HeapTupleGetDatum (resultTuple );
279-
280- inter_call_data -> offset ++ ;
281- SRF_RETURN_NEXT (fctx , result );
259+ tuplestore_putvalues (tupstore , tupdesc , values , nulls );
282260 }
283261
284- relation_close (inter_call_data -> rel , AccessShareLock );
262+ relation_close (indexRel , AccessShareLock );
285263
286- SRF_RETURN_DONE ( fctx ) ;
264+ return ( Datum ) 0 ;
287265}
0 commit comments