Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ab6676b

Browse files
author
Nikita Glukhov
committed
Extract jsonStatsGetArrayIndexStatsTuple() from jsonStatsGetPathStats()
1 parent c189315 commit ab6676b

File tree

1 file changed

+54
-49
lines changed

1 file changed

+54
-49
lines changed

src/backend/utils/adt/jsonb_selfuncs.c

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "catalog/pg_operator.h"
2222
#include "catalog/pg_statistic.h"
2323
#include "catalog/pg_type.h"
24+
#include "common/string.h"
2425
#include "nodes/primnodes.h"
2526
#include "utils/builtins.h"
2627
#include "utils/json.h"
@@ -378,66 +379,48 @@ jsonPathStatsGetArrayIndexSelectivity(JsonPathStats pstats, int index)
378379

379380
/*
380381
* jsonStatsGetPathStats
381-
* ???
382+
* Find JSON statistics for a given path.
382383
*
383-
* XXX I guess pathLen stored number of pathEntries elements, so it should be
384-
* nEntries or something. pathLen implies it's a string length.
384+
* 'path' is an array of text datums of length 'pathlen' (can be zero).
385385
*/
386386
static JsonPathStats
387-
jsonStatsGetPathStats(JsonStats jsdata, Datum *pathEntries, int pathLen,
387+
jsonStatsGetPathStats(JsonStats jsdata, Datum *path, int pathlen,
388388
float4 *nullfrac)
389389
{
390-
JsonPathStats pstats;
390+
JsonPathStats pstats = jsonStatsGetPathStatsStr(jsdata, "$", 1);
391391
Selectivity sel = 1.0;
392-
int i;
393392

394-
if (!pathEntries && pathLen < 0)
393+
for (int i = 0; pstats && i < pathlen; i++)
395394
{
396-
if ((pstats = jsonStatsGetPathStatsStr(jsdata, "$.#", 3)))
395+
char *key = text_to_cstring(DatumGetTextP(path[i]));
396+
int keylen = strlen(key);
397+
char *tail;
398+
int index;
399+
400+
/* Try to interpret path entry as integer array index */
401+
errno = 0;
402+
index = strtoint(key, &tail, 10);
403+
404+
if (tail == key || *tail != '\0' || errno != 0)
397405
{
398-
sel = jsonPathStatsGetArrayIndexSelectivity(pstats, -1 - pathLen);
399-
sel /= jsonPathStatsGetFreq(pstats, 0.0);
406+
/* Find object key stats */
407+
pstats = jsonPathStatsGetSubpath(pstats, key, keylen);
400408
}
401-
}
402-
else
403-
{
404-
pstats = jsonStatsGetPathStatsStr(jsdata, "$", 1);
405-
406-
for (i = 0; pstats && i < pathLen; i++)
409+
else
407410
{
408-
char *key = text_to_cstring(DatumGetTextP(pathEntries[i]));
409-
int keylen = strlen(key);
411+
/* Find array index stats */
412+
float4 arrfreq;
410413

411-
/* XXX What's this key "0123456789" about? */
412-
if (key[0] >= '0' && key[0] <= '9' &&
413-
key[strspn(key, "0123456789")] == '\0')
414-
{
415-
char *tail;
416-
long index;
417-
418-
errno = 0;
419-
index = strtol(key, &tail, 10);
420-
421-
if (*tail || errno || index > INT_MAX || index < 0)
422-
pstats = jsonPathStatsGetSubpath(pstats, key, keylen);
423-
else
424-
{
425-
float4 arrfreq;
426-
427-
/* FIXME consider key also */
428-
pstats = jsonPathStatsGetSubpath(pstats, NULL, 0);
429-
sel *= jsonPathStatsGetArrayIndexSelectivity(pstats, index);
430-
arrfreq = jsonPathStatsGetFreq(pstats, 0.0);
431-
432-
if (arrfreq > 0.0)
433-
sel /= arrfreq;
434-
}
435-
}
436-
else
437-
pstats = jsonPathStatsGetSubpath(pstats, key, keylen);
414+
/* FIXME consider object key "index" also */
415+
pstats = jsonPathStatsGetSubpath(pstats, NULL, 0);
416+
sel *= jsonPathStatsGetArrayIndexSelectivity(pstats, index);
417+
arrfreq = jsonPathStatsGetFreq(pstats, 0.0);
438418

439-
pfree(key);
419+
if (arrfreq > 0.0)
420+
sel /= arrfreq;
440421
}
422+
423+
pfree(key);
441424
}
442425

443426
*nullfrac = 1.0 - sel;
@@ -844,7 +827,7 @@ jsonPathStatsFormTuple(JsonPathStats pstats, JsonStatType type, float4 nullfrac)
844827

845828
/*
846829
* jsonStatsGetPathStatsTuple
847-
* ???
830+
* Extract JSON statistics for a path and form pg_statistics tuple.
848831
*/
849832
static HeapTuple
850833
jsonStatsGetPathStatsTuple(JsonStats jsdata, JsonStatType type,
@@ -857,6 +840,28 @@ jsonStatsGetPathStatsTuple(JsonStats jsdata, JsonStatType type,
857840
return jsonPathStatsFormTuple(pstats, type, nullfrac);
858841
}
859842

843+
/*
844+
* jsonStatsGetArrayIndexStatsTuple
845+
* Extract JSON statistics for a array index and form pg_statistics tuple.
846+
*/
847+
static HeapTuple
848+
jsonStatsGetArrayIndexStatsTuple(JsonStats jsdata, JsonStatType type, int32 index)
849+
{
850+
/* Extract statistics for root array elements */
851+
JsonPathStats pstats = jsonStatsGetPathStatsStr(jsdata, "$.#", 3);
852+
Selectivity index_sel;
853+
854+
if (!pstats)
855+
return NULL;
856+
857+
/* Compute relative selectivity of 'EXISTS($[index])' */
858+
index_sel = jsonPathStatsGetArrayIndexSelectivity(pstats, index);
859+
index_sel /= jsonPathStatsGetFreq(pstats, 0.0);
860+
861+
/* Form pg_statistics tuple, taking into account array index selectivity */
862+
return jsonPathStatsFormTuple(pstats, type, 1.0 - index_sel);
863+
}
864+
860865
/*
861866
* jsonStatsGetPathFreq
862867
* Return frequency of a path (fraction of documents containing it).
@@ -929,8 +934,8 @@ jsonbStatsVarOpConst(Oid opid, VariableStatData *resdata,
929934
}
930935

931936
resdata->statsTuple =
932-
jsonStatsGetPathStatsTuple(&jsdata, statype, NULL,
933-
-1 - DatumGetInt32(cnst->constvalue));
937+
jsonStatsGetArrayIndexStatsTuple(&jsdata, statype,
938+
DatumGetInt32(cnst->constvalue));
934939
break;
935940
}
936941

0 commit comments

Comments
 (0)