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

Commit4d66285

Browse files
committed
Fix pg_mcv_list_items() to produce text[]
The function pg_mcv_list_items() returns values stored in MCV items. Theitems may contain columns with different data types, so the function wasgenerating text array-like representation, but in an ad-hoc way withoutproperly escaping various characters etc.Fixed by simply building a text[] array, which also makes it easier touse from queries etc.Requires changes to pg_proc entry, so bump catversion.Backpatch to 12, where multi-column MCV lists were introduced.Author: Tomas VondraReviewed-by: Dean RasheedDiscussion:https://postgr.es/m/20190618205920.qtlzcu73whfpfqne@development
1 parente365a58 commit4d66285

File tree

4 files changed

+51
-87
lines changed

4 files changed

+51
-87
lines changed

‎src/backend/statistics/mcv.c

Lines changed: 46 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,9 +1248,6 @@ Datum
12481248
pg_stats_ext_mcvlist_items(PG_FUNCTION_ARGS)
12491249
{
12501250
FuncCallContext*funcctx;
1251-
intcall_cntr;
1252-
intmax_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+
Datumvalues[5];
1297+
boolnulls[5];
13041298
HeapTupletuple;
13051299
Datumresult;
1306-
1307-
StringInfoDataitemValues;
1308-
StringInfoDataitemNulls;
1300+
ArrayBuildState*astate_values=NULL;
1301+
ArrayBuildState*astate_nulls=NULL;
13091302

13101303
inti;
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-
boolisvarlena;
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-
Datumval,
1357-
valout;
1358-
1359-
if (i>0)
1322+
if (!item->isnull[i])
13601323
{
1361-
appendStringInfoString(&itemValues,", ");
1362-
appendStringInfoString(&itemNulls,", ");
1324+
boolisvarlena;
1325+
Oidoutfunc;
1326+
FmgrInfofmgrinfo;
1327+
Datumval;
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 */

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO201907041
56+
#defineCATALOG_VERSION_NO201907051
5757

5858
#endif

‎src/include/catalog/pg_proc.dat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5019,7 +5019,7 @@
50195019
{ oid => '3427', descr => 'details about MCV list items',
50205020
proname => 'pg_mcv_list_items', prorows => '1000', proretset => 't',
50215021
provolatile => 's', prorettype => 'record', proargtypes => 'pg_mcv_list',
5022-
proallargtypes => '{pg_mcv_list,int4,text,_bool,float8,float8}',
5022+
proallargtypes => '{pg_mcv_list,int4,_text,_bool,float8,float8}',
50235023
proargmodes => '{i,o,o,o,o,o}',
50245024
proargnames => '{mcv_list,index,values,nulls,frequency,base_frequency}',
50255025
prosrc => 'pg_stats_ext_mcvlist_items' },

‎src/test/regress/expected/stats_ext.out

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,9 @@ SELECT m.*
614614
pg_mcv_list_items(d.stxdmcv) m
615615
WHERE s.stxname = 'mcv_lists_stats'
616616
AND d.stxoid = s.oid;
617-
index |values | nulls | frequency | base_frequency
618-
-------+-----------+---------+-----------+----------------
619-
0 | {1, 2,3} | {f,f,f} | 1 | 1
617+
index | values | nulls | frequency | base_frequency
618+
-------+---------+---------+-----------+----------------
619+
0 | {1,2,3} | {f,f,f} | 1 | 1
620620
(1 row)
621621

622622
-- mcv with arrays

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp