Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit adece56

Browse files
author
Nikita Glukhov
committed
WIP: jsonpath exists, filters
1 parent 40e6d81 commit adece56

File tree

1 file changed

+125
-33
lines changed

1 file changed

+125
-33
lines changed

jsquery_extract.c

Lines changed: 125 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -305,19 +305,24 @@ makePathItem(PathItemType type, PathItem *parent)
305305
typedef struct ExtractedJsonPath
306306
{
307307
PathItem *path;
308+
List *filters;
308309
bool indirect;
309310
bool type;
310311
} ExtractedJsonPath;
311312

312313
static bool
313314
recursiveExtractJsonPath(JsonPathItem *jpi,
314315
bool lax, bool not, bool indirect, bool unwrap,
315-
PathItem *parent, List **paths);
316+
PathItem *parent, List **paths, List *filters);
317+
318+
static ExtractedNode *
319+
recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not,
320+
PathItem *path);
316321

317322
static bool
318323
recursiveExtractJsonPath2(JsonPathItem *jpi,
319324
bool lax, bool not, bool indirect, bool unwrap,
320-
PathItem *parent, List **paths)
325+
PathItem *parent, List **paths, List *filters)
321326
{
322327
JsonPathItem next;
323328
PathItem *path;
@@ -373,6 +378,24 @@ recursiveExtractJsonPath2(JsonPathItem *jpi,
373378
indirect = true;
374379
break;
375380

381+
case jpiFilter:
382+
{
383+
JsonPathItem arg;
384+
ExtractedNode *expr;
385+
386+
if (not)
387+
return false;
388+
389+
jspGetArg(jpi, &arg);
390+
expr = recursiveExtractJsonPathExpr(&arg, lax, not, parent);
391+
392+
if (expr)
393+
filters = lappend(list_copy(filters), expr);
394+
395+
path = parent;
396+
break;
397+
}
398+
376399
default:
377400
/* elog(ERROR,"Wrong state: %d", jpi->type); */
378401
return false;
@@ -384,6 +407,7 @@ recursiveExtractJsonPath2(JsonPathItem *jpi,
384407
ExtractedJsonPath *ejp = palloc(sizeof(*ejp));
385408

386409
ejp->path = path;
410+
ejp->filters = filters;
387411
ejp->indirect = indirect;
388412
ejp->type = jspHasNext(jpi) && next.type == jpiType;
389413

@@ -394,6 +418,7 @@ recursiveExtractJsonPath2(JsonPathItem *jpi,
394418
{
395419
ejp = palloc(sizeof(*ejp));
396420
ejp->path = makePathItem(iAnyArray, path);
421+
ejp->filters = filters;
397422
ejp->indirect = indirect;
398423
ejp->type = false;
399424

@@ -404,13 +429,13 @@ recursiveExtractJsonPath2(JsonPathItem *jpi,
404429
}
405430

406431
return recursiveExtractJsonPath(&next, lax, not, indirect, unwrap, path,
407-
paths);
432+
paths, filters);
408433
}
409434

410435
static bool
411436
recursiveExtractJsonPath(JsonPathItem *jpi,
412437
bool lax, bool not, bool indirect, bool unwrap,
413-
PathItem *parent, List **paths)
438+
PathItem *parent, List **paths, List *filters)
414439
{
415440
switch (jpi->type)
416441
{
@@ -430,13 +455,14 @@ recursiveExtractJsonPath(JsonPathItem *jpi,
430455
ExtractedJsonPath *ejp = palloc(sizeof(*ejp));
431456

432457
ejp->path = parent;
458+
ejp->filters = filters;
433459
ejp->indirect = indirect;
434460
ejp->type = false;
435461

436462
*paths = lappend(*paths, ejp);
437463
}
438464
else if (!recursiveExtractJsonPath2(&next, lax, not, indirect, unwrap,
439-
parent, paths))
465+
parent, paths, filters))
440466
return false;
441467
}
442468

@@ -448,7 +474,7 @@ recursiveExtractJsonPath(JsonPathItem *jpi,
448474
if (lax &&
449475
!recursiveExtractJsonPath2(jpi, lax, not, true, unwrap,
450476
makePathItem(iAnyArray, parent),
451-
paths))
477+
paths, filters))
452478
return false;
453479
break;
454480

@@ -457,7 +483,7 @@ recursiveExtractJsonPath(JsonPathItem *jpi,
457483
}
458484

459485
return recursiveExtractJsonPath2(jpi, lax, not, indirect, unwrap, parent,
460-
paths);
486+
paths, filters);
461487
}
462488

463489
static inline JsQueryItem *
@@ -496,7 +522,77 @@ jspConstToJsQueryItem(JsonPathItem *jpi)
496522
}
497523

498524
static ExtractedNode *
499-
recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
525+
appendJsonPathExprNode(ExtractedNode *result, ExtractedNode *node, PathItem *path,
526+
List *filters)
527+
{
528+
ExtractedNode *orNode;
529+
530+
if (filters)
531+
{
532+
ListCell *flc;
533+
534+
foreach(flc, filters)
535+
{
536+
ExtractedNode *filter = lfirst(flc);
537+
ExtractedNode *andNode = palloc(sizeof(ExtractedNode));
538+
539+
andNode->type = eAnd;
540+
andNode->hint = jsqIndexDefault;
541+
andNode->path = path;
542+
andNode->indirect = false;
543+
andNode->args.items = palloc(2 * sizeof(ExtractedNode *));
544+
andNode->args.items[0] = node;
545+
andNode->args.items[1] = filter;
546+
andNode->args.count = 2;
547+
548+
node = andNode;
549+
}
550+
}
551+
552+
if (!result)
553+
return node;
554+
555+
orNode = palloc(sizeof(ExtractedNode));
556+
557+
orNode->type = eOr;
558+
orNode->hint = jsqIndexDefault;
559+
orNode->path = path;
560+
orNode->indirect = false;
561+
orNode->args.items = palloc(2 * sizeof(ExtractedNode *));
562+
orNode->args.items[0] = result;
563+
orNode->args.items[1] = node;
564+
orNode->args.count = 2;
565+
566+
return orNode;
567+
}
568+
569+
static ExtractedNode *
570+
extractJsonPathExists(JsonPathItem *jpi, bool lax, PathItem *path)
571+
{
572+
List *paths = NIL;
573+
ListCell *lc;
574+
ExtractedNode *result;
575+
576+
if (!recursiveExtractJsonPath(jpi, lax, false, false /* FIXME */, false,
577+
path, &paths, NIL))
578+
return NULL;
579+
580+
result = NULL;
581+
582+
foreach(lc, paths)
583+
{
584+
ExtractedJsonPath *ejp = lfirst(lc);
585+
ExtractedNode *node = makeAnyNode(false, ejp->indirect, ejp->path);
586+
587+
result = appendJsonPathExprNode(result, node, path, ejp->filters);
588+
}
589+
590+
return result;
591+
}
592+
593+
static ExtractedNode *
594+
recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not,
595+
PathItem *path)
500596
{
501597
ExtractedNode *result;
502598
JsonPathItem elem;
@@ -516,10 +612,10 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
516612
type = ((jpi->type == jpiAnd) == not) ? eOr : eAnd;
517613

518614
jspGetLeftArg(jpi, &elem);
519-
leftNode = recursiveExtractJsonPathExpr(&elem, lax, not);
615+
leftNode = recursiveExtractJsonPathExpr(&elem, lax, not, path);
520616

521617
jspGetRightArg(jpi, &elem);
522-
rightNode = recursiveExtractJsonPathExpr(&elem, lax, not);
618+
rightNode = recursiveExtractJsonPathExpr(&elem, lax, not, path);
523619

524620
if (!leftNode || !rightNode)
525621
{
@@ -540,7 +636,7 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
540636

541637
result = palloc(sizeof(ExtractedNode));
542638
result->type = type;
543-
result->path = NULL;
639+
result->path = path;
544640
result->indirect = indirect;
545641
result->args.items = palloc(2 * sizeof(ExtractedNode *));
546642
result->args.items[0] = leftNode;
@@ -552,7 +648,7 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
552648

553649
case jpiNot:
554650
jspGetArg(jpi, &elem);
555-
return recursiveExtractJsonPathExpr(&elem, lax, !not);
651+
return recursiveExtractJsonPathExpr(&elem, lax, !not, path);
556652

557653
case jpiEqual:
558654
case jpiLess:
@@ -585,8 +681,8 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
585681
{
586682
bound = jspConstToJsQueryItem(&rarg);
587683

588-
if (!recursiveExtractJsonPath(&larg, lax, not, false/* FIXME */, true, NULL,
589-
&paths))
684+
if (!recursiveExtractJsonPath(&larg, lax, not, false/* FIXME */, true, path,
685+
&paths, NIL))
590686
return NULL;
591687
}
592688
else if (larg.type == jpiNumeric ||
@@ -597,8 +693,8 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
597693
{
598694
bound = jspConstToJsQueryItem(&larg);
599695

600-
if (!recursiveExtractJsonPath(&rarg, lax, not, false/* FIXME */, true, NULL,
601-
&paths))
696+
if (!recursiveExtractJsonPath(&rarg, lax, not, false/* FIXME */, true, path,
697+
&paths, NIL))
602698
return NULL;
603699

604700
greater = !greater;
@@ -674,27 +770,23 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
674770
}
675771
}
676772

677-
if (result)
678-
{
679-
ExtractedNode *orNode = palloc(sizeof(ExtractedNode));
680-
681-
orNode->type = eOr;
682-
orNode->path = NULL;
683-
orNode->indirect = false;
684-
orNode->args.items = palloc(2 * sizeof(ExtractedNode *));
685-
orNode->args.items[0] = result;
686-
orNode->args.items[1] = node;
687-
orNode->args.count = 2;
688-
689-
result = orNode;
690-
}
691-
else
692-
result = node;
773+
result = appendJsonPathExprNode(result, node, path,
774+
ejp->filters);
693775
}
694776

695777
return result;
696778
}
697779

780+
case jpiExists:
781+
{
782+
if (not)
783+
return NULL;
784+
785+
jspGetArg(jpi, &elem);
786+
787+
return extractJsonPathExists(&elem, lax, path);
788+
}
789+
698790
default:
699791
/* elog(ERROR,"Wrong state: %d", jpi->type); */
700792
return NULL;
@@ -1262,7 +1354,7 @@ extractJsonPath(JsonPath *jp, MakeEntryHandler makeHandler,
12621354
bool lax = (jp->header & JSONPATH_LAX) != 0;
12631355

12641356
jspInit(&jsp, jp);
1265-
root = recursiveExtractJsonPathExpr(&jsp, lax, false);
1357+
root = recursiveExtractJsonPathExpr(&jsp, lax, false, NULL);
12661358
if (root)
12671359
{
12681360
flatternTree(root);

0 commit comments

Comments
 (0)