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

Commit fd9c5a8

Browse files
author
Nikita Glukhov
committed
Add jsonpath lambda expressions
1 parent 74967ba commit fd9c5a8

File tree

7 files changed

+468
-7
lines changed

7 files changed

+468
-7
lines changed

src/backend/utils/adt/jsonpath.c

Lines changed: 129 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ copyJsonPathItem(JsonPathContext *cxt, JsonPathItem *item, int level,
328328
case jpiKey:
329329
case jpiString:
330330
case jpiVariable:
331+
case jpiArgument:
331332
{
332333
int32 len;
333334
char *data = jspGetString(item, &len);
@@ -542,6 +543,39 @@ copyJsonPathItem(JsonPathContext *cxt, JsonPathItem *item, int level,
542543
}
543544
break;
544545

546+
case jpiLambda:
547+
{
548+
JsonPathItem arg;
549+
int32 nparams = item->content.lambda.nparams;
550+
int offset;
551+
int32 elempos;
552+
int32 i;
553+
554+
/* assign cache id */
555+
appendBinaryStringInfo(buf, (const char *) &cxt->id, sizeof(cxt->id));
556+
++cxt->id;
557+
558+
appendBinaryStringInfo(buf, (char *) &nparams, sizeof(nparams));
559+
offset = buf->len;
560+
561+
appendStringInfoSpaces(buf, sizeof(int32) * (nparams + 1));
562+
563+
for (i = 0; i < nparams; i++)
564+
{
565+
jspGetLambdaParam(item, i, &arg);
566+
elempos = copyJsonPathItem(cxt, &arg, level, NULL, NULL);
567+
*(int32 *) &buf->data[offset] = elempos - pos;
568+
offset += sizeof(int32);
569+
}
570+
571+
jspGetLambdaExpr(item, &arg);
572+
elempos = copyJsonPathItem(cxt, &arg, level, NULL, NULL);
573+
574+
*(int32 *) &buf->data[offset] = elempos - pos;
575+
offset += sizeof(int32);
576+
}
577+
break;
578+
545579
default:
546580
elog(ERROR, "Unknown jsonpath item type: %d", item->type);
547581
}
@@ -608,6 +642,7 @@ flattenJsonPathParseItem(JsonPathContext *cxt, JsonPathParseItem *item,
608642
case jpiString:
609643
case jpiVariable:
610644
case jpiKey:
645+
case jpiArgument:
611646
appendBinaryStringInfo(buf, (char *) &item->value.string.len,
612647
sizeof(item->value.string.len));
613648
appendBinaryStringInfo(buf, item->value.string.val,
@@ -701,6 +736,38 @@ flattenJsonPathParseItem(JsonPathContext *cxt, JsonPathParseItem *item,
701736
*(int32 *) (buf->data + arg) = chld - pos;
702737
}
703738
break;
739+
case jpiLambda:
740+
{
741+
int32 nelems = list_length(item->value.lambda.params);
742+
ListCell *lc;
743+
int offset;
744+
int32 elempos;
745+
746+
/* assign cache id */
747+
appendBinaryStringInfo(buf, (const char *) &cxt->id, sizeof(cxt->id));
748+
++cxt->id;
749+
750+
appendBinaryStringInfo(buf, (char *) &nelems, sizeof(nelems));
751+
offset = buf->len;
752+
753+
appendStringInfoSpaces(buf, sizeof(int32) * (nelems + 1));
754+
755+
foreach(lc, item->value.lambda.params)
756+
{
757+
elempos = flattenJsonPathParseItem(cxt, lfirst(lc),
758+
nestingLevel,
759+
insideArraySubscript);
760+
*(int32 *) &buf->data[offset] = elempos - pos;
761+
offset += sizeof(int32);
762+
}
763+
764+
elempos = flattenJsonPathParseItem(cxt, item->value.lambda.expr,
765+
nestingLevel,
766+
insideArraySubscript);
767+
*(int32 *) &buf->data[offset] = elempos - pos;
768+
offset += sizeof(int32);
769+
}
770+
break;
704771
case jpiNull:
705772
break;
706773
case jpiRoot:
@@ -917,6 +984,9 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
917984
appendStringInfoChar(buf, '$');
918985
escape_json(buf, jspGetString(v, NULL));
919986
break;
987+
case jpiArgument:
988+
appendStringInfoString(buf, jspGetString(v, NULL));
989+
break;
920990
case jpiNumeric:
921991
appendStringInfoString(buf,
922992
DatumGetCString(DirectFunctionCall1(numeric_out,
@@ -1183,6 +1253,31 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
11831253

11841254
appendStringInfoChar(buf, '}');
11851255
break;
1256+
case jpiLambda:
1257+
if (printBracketes || jspHasNext(v))
1258+
appendStringInfoChar(buf, '(');
1259+
1260+
appendStringInfoChar(buf, '(');
1261+
1262+
for (i = 0; i < v->content.lambda.nparams; i++)
1263+
{
1264+
JsonPathItem elem;
1265+
1266+
if (i)
1267+
appendBinaryStringInfo(buf, ", ", 2);
1268+
1269+
jspGetLambdaParam(v, i, &elem);
1270+
printJsonPathItem(buf, &elem, false, false);
1271+
}
1272+
1273+
appendStringInfoString(buf, ") => ");
1274+
1275+
jspGetLambdaExpr(v, &elem);
1276+
printJsonPathItem(buf, &elem, false, false);
1277+
1278+
if (printBracketes || jspHasNext(v))
1279+
appendStringInfoChar(buf, ')');
1280+
break;
11861281
default:
11871282
elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
11881283
}
@@ -1350,6 +1445,7 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
13501445
case jpiKey:
13511446
case jpiString:
13521447
case jpiVariable:
1448+
case jpiArgument:
13531449
read_int32(v->content.value.datalen, base, pos);
13541450
/* FALLTHROUGH */
13551451
case jpiNumeric:
@@ -1380,6 +1476,13 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
13801476
read_int32(v->content.like_regex.patternlen, base, pos);
13811477
v->content.like_regex.pattern = base + pos;
13821478
break;
1479+
case jpiLambda:
1480+
read_int32(v->content.lambda.id, base, pos);
1481+
read_int32(v->content.lambda.nparams, base, pos);
1482+
read_int32_n(v->content.lambda.params, base, pos,
1483+
v->content.lambda.nparams);
1484+
read_int32(v->content.lambda.expr, base, pos);
1485+
break;
13831486
case jpiNot:
13841487
case jpiExists:
13851488
case jpiIsUnknown:
@@ -1476,7 +1579,9 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
14761579
v->type == jpiStartsWith ||
14771580
v->type == jpiSequence ||
14781581
v->type == jpiArray ||
1479-
v->type == jpiObject);
1582+
v->type == jpiObject ||
1583+
v->type == jpiLambda ||
1584+
v->type == jpiArgument);
14801585

14811586
if (a)
14821587
jspInitByBuffer(a, v->base, v->nextPos);
@@ -1551,7 +1656,8 @@ jspGetString(JsonPathItem *v, int32 *len)
15511656
{
15521657
Assert(v->type == jpiKey ||
15531658
v->type == jpiString ||
1554-
v->type == jpiVariable);
1659+
v->type == jpiVariable ||
1660+
v->type == jpiArgument);
15551661

15561662
if (len)
15571663
*len = v->content.value.datalen;
@@ -1590,6 +1696,27 @@ jspGetObjectField(JsonPathItem *v, int i, JsonPathItem *key, JsonPathItem *val)
15901696
jspInitByBuffer(val, v->base, v->content.object.fields[i].val);
15911697
}
15921698

1699+
JsonPathItem *
1700+
jspGetLambdaParam(JsonPathItem *lambda, int index, JsonPathItem *arg)
1701+
{
1702+
Assert(lambda->type == jpiLambda);
1703+
Assert(index < lambda->content.lambda.nparams);
1704+
1705+
jspInitByBuffer(arg, lambda->base, lambda->content.lambda.params[index]);
1706+
1707+
return arg;
1708+
}
1709+
1710+
JsonPathItem *
1711+
jspGetLambdaExpr(JsonPathItem *lambda, JsonPathItem *expr)
1712+
{
1713+
Assert(lambda->type == jpiLambda);
1714+
1715+
jspInitByBuffer(expr, lambda->base, lambda->content.lambda.expr);
1716+
1717+
return expr;
1718+
}
1719+
15931720
static void
15941721
checkJsonPathArgsMismatch(JsonPath *jp1, JsonPath *jp2)
15951722
{

0 commit comments

Comments
 (0)