21
21
#include "catalog/pg_operator.h"
22
22
#include "catalog/pg_statistic.h"
23
23
#include "catalog/pg_type.h"
24
+ #include "common/string.h"
24
25
#include "nodes/primnodes.h"
25
26
#include "utils/builtins.h"
26
27
#include "utils/json.h"
@@ -378,66 +379,48 @@ jsonPathStatsGetArrayIndexSelectivity(JsonPathStats pstats, int index)
378
379
379
380
/*
380
381
* jsonStatsGetPathStats
381
- * ???
382
+ * Find JSON statistics for a given path.
382
383
*
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).
385
385
*/
386
386
static JsonPathStats
387
- jsonStatsGetPathStats (JsonStats jsdata , Datum * pathEntries , int pathLen ,
387
+ jsonStatsGetPathStats (JsonStats jsdata , Datum * path , int pathlen ,
388
388
float4 * nullfrac )
389
389
{
390
- JsonPathStats pstats ;
390
+ JsonPathStats pstats = jsonStatsGetPathStatsStr ( jsdata , "$" , 1 ) ;
391
391
Selectivity sel = 1.0 ;
392
- int i ;
393
392
394
- if (! pathEntries && pathLen < 0 )
393
+ for ( int i = 0 ; pstats && i < pathlen ; i ++ )
395
394
{
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 )
397
405
{
398
- sel = jsonPathStatsGetArrayIndexSelectivity ( pstats , -1 - pathLen );
399
- sel /= jsonPathStatsGetFreq (pstats , 0.0 );
406
+ /* Find object key stats */
407
+ pstats = jsonPathStatsGetSubpath (pstats , key , keylen );
400
408
}
401
- }
402
- else
403
- {
404
- pstats = jsonStatsGetPathStatsStr (jsdata , "$" , 1 );
405
-
406
- for (i = 0 ; pstats && i < pathLen ; i ++ )
409
+ else
407
410
{
408
- char * key = text_to_cstring ( DatumGetTextP ( pathEntries [ i ]));
409
- int keylen = strlen ( key ) ;
411
+ /* Find array index stats */
412
+ float4 arrfreq ;
410
413
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 );
438
418
439
- pfree (key );
419
+ if (arrfreq > 0.0 )
420
+ sel /= arrfreq ;
440
421
}
422
+
423
+ pfree (key );
441
424
}
442
425
443
426
* nullfrac = 1.0 - sel ;
@@ -844,7 +827,7 @@ jsonPathStatsFormTuple(JsonPathStats pstats, JsonStatType type, float4 nullfrac)
844
827
845
828
/*
846
829
* jsonStatsGetPathStatsTuple
847
- * ???
830
+ * Extract JSON statistics for a path and form pg_statistics tuple.
848
831
*/
849
832
static HeapTuple
850
833
jsonStatsGetPathStatsTuple (JsonStats jsdata , JsonStatType type ,
@@ -857,6 +840,28 @@ jsonStatsGetPathStatsTuple(JsonStats jsdata, JsonStatType type,
857
840
return jsonPathStatsFormTuple (pstats , type , nullfrac );
858
841
}
859
842
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
+
860
865
/*
861
866
* jsonStatsGetPathFreq
862
867
* Return frequency of a path (fraction of documents containing it).
@@ -929,8 +934,8 @@ jsonbStatsVarOpConst(Oid opid, VariableStatData *resdata,
929
934
}
930
935
931
936
resdata -> statsTuple =
932
- jsonStatsGetPathStatsTuple (& jsdata , statype , NULL ,
933
- -1 - DatumGetInt32 (cnst -> constvalue ));
937
+ jsonStatsGetArrayIndexStatsTuple (& jsdata , statype ,
938
+ DatumGetInt32 (cnst -> constvalue ));
934
939
break ;
935
940
}
936
941
0 commit comments