@@ -1248,9 +1248,6 @@ Datum
12481248pg_stats_ext_mcvlist_items (PG_FUNCTION_ARGS )
12491249{
12501250 FuncCallContext * funcctx ;
1251- int call_cntr ;
1252- int max_calls ;
1253- AttInMetadata * attinmeta ;
12541251
12551252 /* stuff done only on the first call of the function */
12561253 if (SRF_IS_FIRSTCALL ())
@@ -1280,125 +1277,92 @@ pg_stats_ext_mcvlist_items(PG_FUNCTION_ARGS)
12801277 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
12811278 errmsg ("function returning record called in context "
12821279 "that cannot accept type record" )));
1280+ tupdesc = BlessTupleDesc (tupdesc );
12831281
12841282 /*
12851283 * generate attribute metadata needed later to produce tuples from raw
12861284 * C strings
12871285 */
1288- attinmeta = TupleDescGetAttInMetadata (tupdesc );
1289- funcctx -> attinmeta = attinmeta ;
1286+ funcctx -> attinmeta = TupleDescGetAttInMetadata (tupdesc );
12901287
12911288 MemoryContextSwitchTo (oldcontext );
12921289 }
12931290
12941291 /* stuff done on every call of the function */
12951292 funcctx = SRF_PERCALL_SETUP ();
12961293
1297- call_cntr = funcctx -> call_cntr ;
1298- max_calls = funcctx -> max_calls ;
1299- attinmeta = funcctx -> attinmeta ;
1300-
1301- if (call_cntr < max_calls ) /* do when there is more left to send */
1294+ if (funcctx -> call_cntr < funcctx -> max_calls ) /* do when there is more left to send */
13021295 {
1303- char * * values ;
1296+ Datum values [5 ];
1297+ bool nulls [5 ];
13041298 HeapTuple tuple ;
13051299 Datum result ;
1306-
1307- StringInfoData itemValues ;
1308- StringInfoData itemNulls ;
1300+ ArrayBuildState * astate_values = NULL ;
1301+ ArrayBuildState * astate_nulls = NULL ;
13091302
13101303 int i ;
1311-
1312- Oid * outfuncs ;
1313- FmgrInfo * fmgrinfo ;
1314-
13151304 MCVList * mcvlist ;
13161305 MCVItem * item ;
13171306
13181307 mcvlist = (MCVList * ) funcctx -> user_fctx ;
13191308
1320- Assert (call_cntr < mcvlist -> nitems );
1321-
1322- item = & mcvlist -> items [call_cntr ];
1323-
1324- /*
1325- * Prepare a values array for building the returned tuple. This should
1326- * be an array of C strings which will be processed later by the type
1327- * input functions.
1328- */
1329- values = (char * * ) palloc0 (5 * sizeof (char * ));
1330-
1331- values [0 ] = (char * ) palloc (64 * sizeof (char )); /* item index */
1332- values [3 ] = (char * ) palloc (64 * sizeof (char )); /* frequency */
1333- values [4 ] = (char * ) palloc (64 * sizeof (char )); /* base frequency */
1309+ Assert (funcctx -> call_cntr < mcvlist -> nitems );
13341310
1335- outfuncs = (Oid * ) palloc0 (sizeof (Oid ) * mcvlist -> ndimensions );
1336- fmgrinfo = (FmgrInfo * ) palloc0 (sizeof (FmgrInfo ) * mcvlist -> ndimensions );
1311+ item = & mcvlist -> items [funcctx -> call_cntr ];
13371312
13381313 for (i = 0 ; i < mcvlist -> ndimensions ; i ++ )
13391314 {
1340- bool isvarlena ;
1341-
1342- getTypeOutputInfo (mcvlist -> types [i ], & outfuncs [i ], & isvarlena );
1343-
1344- fmgr_info (outfuncs [i ], & fmgrinfo [i ]);
1345- }
13461315
1347- /* build the arrays of values / nulls */
1348- initStringInfo (& itemValues );
1349- initStringInfo (& itemNulls );
1316+ astate_nulls = accumArrayResult (astate_nulls ,
1317+ BoolGetDatum (item -> isnull [i ]),
1318+ false,
1319+ BOOLOID ,
1320+ CurrentMemoryContext );
13501321
1351- appendStringInfoChar (& itemValues , '{' );
1352- appendStringInfoChar (& itemNulls , '{' );
1353-
1354- for (i = 0 ; i < mcvlist -> ndimensions ; i ++ )
1355- {
1356- Datum val ,
1357- valout ;
1358-
1359- if (i > 0 )
1322+ if (!item -> isnull [i ])
13601323 {
1361- appendStringInfoString (& itemValues , ", " );
1362- appendStringInfoString (& itemNulls , ", " );
1324+ bool isvarlena ;
1325+ Oid outfunc ;
1326+ FmgrInfo fmgrinfo ;
1327+ Datum val ;
1328+ text * txt ;
1329+
1330+ /* lookup output func for the type */
1331+ getTypeOutputInfo (mcvlist -> types [i ], & outfunc , & isvarlena );
1332+ fmgr_info (outfunc , & fmgrinfo );
1333+
1334+ val = FunctionCall1 (& fmgrinfo , item -> values [i ]);
1335+ txt = cstring_to_text (DatumGetPointer (val ));
1336+
1337+ astate_values = accumArrayResult (astate_values ,
1338+ PointerGetDatum (txt ),
1339+ false,
1340+ TEXTOID ,
1341+ CurrentMemoryContext );
13631342 }
1364-
1365- if (item -> isnull [i ])
1366- valout = CStringGetDatum ("NULL" );
13671343 else
1368- {
1369- val = item -> values [i ];
1370- valout = FunctionCall1 (& fmgrinfo [i ], val );
1371- }
1372-
1373- appendStringInfoString (& itemValues , DatumGetCString (valout ));
1374- appendStringInfoString (& itemNulls , item -> isnull [i ] ? "t" : "f" );
1344+ astate_values = accumArrayResult (astate_values ,
1345+ (Datum ) 0 ,
1346+ true,
1347+ TEXTOID ,
1348+ CurrentMemoryContext );
13751349 }
13761350
1377- appendStringInfoChar (& itemValues , '}' );
1378- appendStringInfoChar (& itemNulls , '}' );
1379-
1380- snprintf (values [0 ], 64 , "%d" , call_cntr );
1381- snprintf (values [3 ], 64 , "%f" , item -> frequency );
1382- snprintf (values [4 ], 64 , "%f" , item -> base_frequency );
1351+ values [0 ] = Int32GetDatum (funcctx -> call_cntr );
1352+ values [1 ] = PointerGetDatum (makeArrayResult (astate_values , CurrentMemoryContext ));
1353+ values [2 ] = PointerGetDatum (makeArrayResult (astate_nulls , CurrentMemoryContext ));
1354+ values [3 ] = Float8GetDatum (item -> frequency );
1355+ values [4 ] = Float8GetDatum (item -> base_frequency );
13831356
1384- values [ 1 ] = itemValues . data ;
1385- values [ 2 ] = itemNulls . data ;
1357+ /* no NULLs in the tuple */
1358+ memset ( nulls , 0 , sizeof ( nulls )) ;
13861359
13871360 /* build a tuple */
1388- tuple = BuildTupleFromCStrings ( attinmeta , values );
1361+ tuple = heap_form_tuple ( funcctx -> attinmeta -> tupdesc , values , nulls );
13891362
13901363 /* make the tuple into a datum */
13911364 result = HeapTupleGetDatum (tuple );
13921365
1393- /* clean up (this is not really necessary) */
1394- pfree (itemValues .data );
1395- pfree (itemNulls .data );
1396-
1397- pfree (values [0 ]);
1398- pfree (values [3 ]);
1399- pfree (values [4 ]);
1400- pfree (values );
1401-
14021366 SRF_RETURN_NEXT (funcctx , result );
14031367 }
14041368 else /* do when there is no more left */
0 commit comments