@@ -92,65 +92,56 @@ gist_page_opaque_info(PG_FUNCTION_ARGS)
92
92
return HeapTupleGetDatum (resultTuple );
93
93
}
94
94
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
-
103
95
Datum
104
96
gist_page_items_bytea (PG_FUNCTION_ARGS )
105
97
{
106
98
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 ;
109
106
110
107
if (!superuser ())
111
108
ereport (ERROR ,
112
109
(errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
113
110
errmsg ("must be superuser to use raw page functions" )));
114
111
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" )));
127
121
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 );
131
124
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 " );
134
127
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 ;
138
133
139
- fctx -> max_calls = PageGetMaxOffsetNumber (page );
140
- fctx -> user_fctx = inter_call_data ;
134
+ MemoryContextSwitchTo (oldcontext );
141
135
142
- MemoryContextSwitchTo (mctx );
143
- }
136
+ page = get_page_from_raw (raw_page );
144
137
145
- fctx = SRF_PERCALL_SETUP ();
146
- inter_call_data = fctx -> user_fctx ;
138
+ if ( GistPageIsDeleted ( page ))
139
+ elog ( NOTICE , "page is deleted" ) ;
147
140
148
- if (fctx -> call_cntr < fctx -> max_calls )
141
+ for (offset = FirstOffsetNumber ;
142
+ offset <= PageGetMaxOffsetNumber (page );
143
+ offset ++ )
149
144
{
150
- Page page = inter_call_data -> page ;
151
- OffsetNumber offset = inter_call_data -> offset ;
152
- HeapTuple resultTuple ;
153
- Datum result ;
154
145
Datum values [4 ];
155
146
bool nulls [4 ];
156
147
ItemId id ;
@@ -177,74 +168,67 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
177
168
memcpy (VARDATA (tuple_bytea ), itup , tuple_len );
178
169
values [3 ] = PointerGetDatum (tuple_bytea );
179
170
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 );
186
172
}
187
173
188
- SRF_RETURN_DONE ( fctx ) ;
174
+ return ( Datum ) 0 ;
189
175
}
190
176
191
177
Datum
192
178
gist_page_items (PG_FUNCTION_ARGS )
193
179
{
194
180
bytea * raw_page = PG_GETARG_BYTEA_P (0 );
195
181
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 ;
198
190
199
191
if (!superuser ())
200
192
ereport (ERROR ,
201
193
(errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
202
194
errmsg ("must be superuser to use raw page functions" )));
203
195
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" )));
217
205
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 );
220
208
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" );
224
211
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 ;
227
217
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 );
232
219
233
- fctx -> max_calls = PageGetMaxOffsetNumber ( page );
234
- fctx -> user_fctx = inter_call_data ;
220
+ /* Open the relation */
221
+ indexRel = index_open ( indexRelid , AccessShareLock ) ;
235
222
236
- MemoryContextSwitchTo (mctx );
237
- }
223
+ page = get_page_from_raw (raw_page );
238
224
239
- fctx = SRF_PERCALL_SETUP ();
240
- inter_call_data = fctx -> user_fctx ;
225
+ if ( GistPageIsDeleted ( page ))
226
+ elog ( NOTICE , "page is deleted" ) ;
241
227
242
- if (fctx -> call_cntr < fctx -> max_calls )
228
+ for (offset = FirstOffsetNumber ;
229
+ offset <= PageGetMaxOffsetNumber (page );
230
+ offset ++ )
243
231
{
244
- Page page = inter_call_data -> page ;
245
- OffsetNumber offset = inter_call_data -> offset ;
246
- HeapTuple resultTuple ;
247
- Datum result ;
248
232
Datum values [4 ];
249
233
bool nulls [4 ];
250
234
ItemId id ;
@@ -260,11 +244,10 @@ gist_page_items(PG_FUNCTION_ARGS)
260
244
261
245
itup = (IndexTuple ) PageGetItem (page , id );
262
246
263
- index_deform_tuple (itup , RelationGetDescr (inter_call_data -> rel ),
247
+ index_deform_tuple (itup , RelationGetDescr (indexRel ),
264
248
itup_values , itup_isnull );
265
249
266
- key_desc = BuildIndexValueDescription (inter_call_data -> rel , itup_values ,
267
- itup_isnull );
250
+ key_desc = BuildIndexValueDescription (indexRel , itup_values , itup_isnull );
268
251
269
252
memset (nulls , 0 , sizeof (nulls ));
270
253
@@ -273,15 +256,10 @@ gist_page_items(PG_FUNCTION_ARGS)
273
256
values [2 ] = Int32GetDatum ((int ) IndexTupleSize (itup ));
274
257
values [3 ] = CStringGetTextDatum (key_desc );
275
258
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 );
282
260
}
283
261
284
- relation_close (inter_call_data -> rel , AccessShareLock );
262
+ relation_close (indexRel , AccessShareLock );
285
263
286
- SRF_RETURN_DONE ( fctx ) ;
264
+ return ( Datum ) 0 ;
287
265
}
0 commit comments