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

Commit 2ea748c

Browse files
author
Nikita Glukhov
committed
Refactor jsonPathStatsGetNextSubpathStats(), add more comments
1 parent 8f28575 commit 2ea748c

File tree

2 files changed

+54
-29
lines changed

2 files changed

+54
-29
lines changed

src/backend/utils/adt/jsonb_selfuncs.c

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -440,14 +440,22 @@ jsonStatsGetPath(JsonStats jsdata, Datum *path, int pathlen, float4 *nullfrac)
440440
}
441441

442442
/*
443-
* jsonPathStatsGetNextKeyStats
444-
* Enumerate all collected object keys.
443+
* jsonPathStatsGetNextSubpathStats
444+
* Iterate all collected subpaths of a given path.
445445
*
446-
* This can be useful for estimation of selectivity of jsonpath '.*' operator.
446+
* This function can be useful for estimation of selectivity of jsonpath
447+
* '.*' and '.**' operators.
448+
*
449+
* The next found subpath is written into *pkeystats, which should be set to
450+
* NULL before the first call.
451+
*
452+
* If keysOnly is true, emit only top-level object-key subpaths.
453+
*
454+
* Returns false on the end of iteration and true otherwise.
447455
*/
448456
bool
449-
jsonPathStatsGetNextKeyStats(JsonPathStats stats, JsonPathStats *pkeystats,
450-
bool keysOnly)
457+
jsonPathStatsGetNextSubpathStats(JsonPathStats stats, JsonPathStats *pkeystats,
458+
bool keysOnly)
451459
{
452460
JsonPathStats keystats = *pkeystats;
453461
int index =
@@ -457,53 +465,69 @@ jsonPathStatsGetNextKeyStats(JsonPathStats stats, JsonPathStats *pkeystats,
457465
{
458466
JsonbValue pathkey;
459467
JsonbValue *jbvpath;
460-
Jsonb *jb = DatumGetJsonbP(stats->data->values[index]);
468+
Datum *pdatum = &stats->data->values[index];
469+
Jsonb *jb = DatumGetJsonbP(*pdatum);
470+
const char *path;
471+
int pathlen;
461472

462473
JsonValueInitStringWithLen(&pathkey, "path", 4);
463474
jbvpath = findJsonbValueFromContainer(&jb->root, JB_FOBJECT, &pathkey);
464475

465-
if (jbvpath->type != jbvString ||
466-
jbvpath->val.string.len <= stats->pathlen ||
467-
memcmp(jbvpath->val.string.val, stats->path, stats->pathlen))
476+
if (jbvpath->type != jbvString)
477+
break; /* invalid path stats */
478+
479+
path = jbvpath->val.string.val;
480+
pathlen = jbvpath->val.string.len;
481+
482+
/* Break, if subpath does not start from a desired prefix */
483+
if (pathlen <= stats->pathlen ||
484+
memcmp(path, stats->path, stats->pathlen))
468485
break;
469486

470487
if (keysOnly)
471488
{
472-
const char *c = &jbvpath->val.string.val[stats->pathlen];
489+
const char *c = &path[stats->pathlen];
473490

474491
if (*c == '[')
475492
{
476-
c++;
477-
Assert(*c == '*');
478-
c++;
479-
Assert(*c == ']');
493+
Assert(c[1] == '*' && c[2] == ']');
480494

481-
if (keysOnly || jbvpath->val.string.len > stats->pathlen + 2)
482-
continue;
495+
#if 0 /* TODO add separate flag for requesting top-level array accessors */
496+
/* skip if it is not last key in the path */
497+
if (pathlen > stats->pathlen + 3)
498+
#endif
499+
continue; /* skip array accessors */
483500
}
484-
else
501+
else if (*c == '.')
485502
{
486-
Assert(*c == '.');
487-
c++;
488-
Assert(*c == '"');
503+
/* find end of '."key"' */
504+
const char *pathend = path + pathlen;
505+
506+
if (++c >= pathend || *c != '"')
507+
break; /* invalid path */
489508

490-
while (*++c != '"')
491-
if (*c == '\\')
509+
while (++c <= pathend && *c != '"')
510+
if (*c == '\\') /* handle escaped chars */
492511
c++;
493512

494-
if (c - jbvpath->val.string.val < jbvpath->val.string.len - 1)
513+
if (c > pathend)
514+
break; /* invalid path */
515+
516+
/* skip if it is not last key in the path */
517+
if (c < pathend)
495518
continue;
496519
}
520+
else
521+
continue; /* invalid path */
497522
}
498523

499524
if (!keystats)
500525
keystats = palloc(sizeof(*keystats));
501526

502-
keystats->datum = &stats->data->values[index];
527+
keystats->datum = pdatum;
503528
keystats->data = stats->data;
504-
keystats->pathlen = jbvpath->val.string.len;
505-
keystats->path = memcpy(palloc(keystats->pathlen),
506-
jbvpath->val.string.val, keystats->pathlen);
529+
keystats->pathlen = pathlen;
530+
keystats->path = memcpy(palloc(pathlen), path, pathlen);
507531
keystats->type = JsonPathStatsValues;
508532

509533
*pkeystats = keystats;

src/include/utils/json_selfuncs.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ extern JsonPathStats jsonStatsGetPathByStr(JsonStats stats,
7676
extern JsonPathStats jsonPathStatsGetSubpath(JsonPathStats stats,
7777
const char *subpath);
7878

79-
extern bool jsonPathStatsGetNextKeyStats(JsonPathStats stats,
80-
JsonPathStats *keystats, bool keysOnly);
79+
extern bool jsonPathStatsGetNextSubpathStats(JsonPathStats stats,
80+
JsonPathStats *keystats,
81+
bool keysOnly);
8182

8283
extern JsonPathStats jsonPathStatsGetLengthStats(JsonPathStats pstats);
8384

0 commit comments

Comments
 (0)