@@ -1248,9 +1248,6 @@ Datum
1248
1248
pg_stats_ext_mcvlist_items (PG_FUNCTION_ARGS )
1249
1249
{
1250
1250
FuncCallContext * funcctx ;
1251
- int call_cntr ;
1252
- int max_calls ;
1253
- AttInMetadata * attinmeta ;
1254
1251
1255
1252
/* stuff done only on the first call of the function */
1256
1253
if (SRF_IS_FIRSTCALL ())
@@ -1280,125 +1277,92 @@ pg_stats_ext_mcvlist_items(PG_FUNCTION_ARGS)
1280
1277
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1281
1278
errmsg ("function returning record called in context "
1282
1279
"that cannot accept type record" )));
1280
+ tupdesc = BlessTupleDesc (tupdesc );
1283
1281
1284
1282
/*
1285
1283
* generate attribute metadata needed later to produce tuples from raw
1286
1284
* C strings
1287
1285
*/
1288
- attinmeta = TupleDescGetAttInMetadata (tupdesc );
1289
- funcctx -> attinmeta = attinmeta ;
1286
+ funcctx -> attinmeta = TupleDescGetAttInMetadata (tupdesc );
1290
1287
1291
1288
MemoryContextSwitchTo (oldcontext );
1292
1289
}
1293
1290
1294
1291
/* stuff done on every call of the function */
1295
1292
funcctx = SRF_PERCALL_SETUP ();
1296
1293
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 */
1302
1295
{
1303
- char * * values ;
1296
+ Datum values [5 ];
1297
+ bool nulls [5 ];
1304
1298
HeapTuple tuple ;
1305
1299
Datum result ;
1306
-
1307
- StringInfoData itemValues ;
1308
- StringInfoData itemNulls ;
1300
+ ArrayBuildState * astate_values = NULL ;
1301
+ ArrayBuildState * astate_nulls = NULL ;
1309
1302
1310
1303
int i ;
1311
-
1312
- Oid * outfuncs ;
1313
- FmgrInfo * fmgrinfo ;
1314
-
1315
1304
MCVList * mcvlist ;
1316
1305
MCVItem * item ;
1317
1306
1318
1307
mcvlist = (MCVList * ) funcctx -> user_fctx ;
1319
1308
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 );
1334
1310
1335
- outfuncs = (Oid * ) palloc0 (sizeof (Oid ) * mcvlist -> ndimensions );
1336
- fmgrinfo = (FmgrInfo * ) palloc0 (sizeof (FmgrInfo ) * mcvlist -> ndimensions );
1311
+ item = & mcvlist -> items [funcctx -> call_cntr ];
1337
1312
1338
1313
for (i = 0 ; i < mcvlist -> ndimensions ; i ++ )
1339
1314
{
1340
- bool isvarlena ;
1341
-
1342
- getTypeOutputInfo (mcvlist -> types [i ], & outfuncs [i ], & isvarlena );
1343
-
1344
- fmgr_info (outfuncs [i ], & fmgrinfo [i ]);
1345
- }
1346
1315
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 );
1350
1321
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 ])
1360
1323
{
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 );
1363
1342
}
1364
-
1365
- if (item -> isnull [i ])
1366
- valout = CStringGetDatum ("NULL" );
1367
1343
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 );
1375
1349
}
1376
1350
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 );
1383
1356
1384
- values [ 1 ] = itemValues . data ;
1385
- values [ 2 ] = itemNulls . data ;
1357
+ /* no NULLs in the tuple */
1358
+ memset ( nulls , 0 , sizeof ( nulls )) ;
1386
1359
1387
1360
/* build a tuple */
1388
- tuple = BuildTupleFromCStrings ( attinmeta , values );
1361
+ tuple = heap_form_tuple ( funcctx -> attinmeta -> tupdesc , values , nulls );
1389
1362
1390
1363
/* make the tuple into a datum */
1391
1364
result = HeapTupleGetDatum (tuple );
1392
1365
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
-
1402
1366
SRF_RETURN_NEXT (funcctx , result );
1403
1367
}
1404
1368
else /* do when there is no more left */
0 commit comments