@@ -136,12 +136,15 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
136
136
case jpiPlus :
137
137
case jpiMinus :
138
138
case jpiExists :
139
+ case jpiArray :
139
140
{
140
- int32 arg ;
141
+ int32 arg = item -> value . arg ? buf -> len : 0 ;
141
142
142
- arg = buf -> len ;
143
143
appendBinaryStringInfo (buf , (char * )& arg /* fake value */ , sizeof (arg ));
144
144
145
+ if (!item -> value .arg )
146
+ break ;
147
+
145
148
chld = flattenJsonPathParseItem (buf , item -> value .arg ,
146
149
nestingLevel + argNestingLevel ,
147
150
insideArraySubscript );
@@ -218,6 +221,61 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
218
221
case jpiDouble :
219
222
case jpiKeyValue :
220
223
break ;
224
+ case jpiSequence :
225
+ {
226
+ int32 nelems = list_length (item -> value .sequence .elems );
227
+ ListCell * lc ;
228
+ int offset ;
229
+
230
+ appendBinaryStringInfo (buf , (char * ) & nelems , sizeof (nelems ));
231
+
232
+ offset = buf -> len ;
233
+
234
+ appendStringInfoSpaces (buf , sizeof (int32 ) * nelems );
235
+
236
+ foreach (lc , item -> value .sequence .elems )
237
+ {
238
+ int32 elempos =
239
+ flattenJsonPathParseItem (buf , lfirst (lc ), nestingLevel ,
240
+ insideArraySubscript );
241
+
242
+ * (int32 * ) & buf -> data [offset ] = elempos - pos ;
243
+ offset += sizeof (int32 );
244
+ }
245
+ }
246
+ break ;
247
+ case jpiObject :
248
+ {
249
+ int32 nfields = list_length (item -> value .object .fields );
250
+ ListCell * lc ;
251
+ int offset ;
252
+
253
+ appendBinaryStringInfo (buf , (char * ) & nfields , sizeof (nfields ));
254
+
255
+ offset = buf -> len ;
256
+
257
+ appendStringInfoSpaces (buf , sizeof (int32 ) * 2 * nfields );
258
+
259
+ foreach (lc , item -> value .object .fields )
260
+ {
261
+ JsonPathParseItem * field = lfirst (lc );
262
+ int32 keypos =
263
+ flattenJsonPathParseItem (buf , field -> value .args .left ,
264
+ nestingLevel ,
265
+ insideArraySubscript );
266
+ int32 valpos =
267
+ flattenJsonPathParseItem (buf , field -> value .args .right ,
268
+ nestingLevel ,
269
+ insideArraySubscript );
270
+ int32 * ppos = (int32 * ) & buf -> data [offset ];
271
+
272
+ ppos [0 ] = keypos - pos ;
273
+ ppos [1 ] = valpos - pos ;
274
+
275
+ offset += 2 * sizeof (int32 );
276
+ }
277
+ }
278
+ break ;
221
279
default :
222
280
elog (ERROR , "Unknown jsonpath item type: %d" , item -> type );
223
281
}
@@ -305,6 +363,8 @@ operationPriority(JsonPathItemType op)
305
363
{
306
364
switch (op )
307
365
{
366
+ case jpiSequence :
367
+ return -1 ;
308
368
case jpiOr :
309
369
return 0 ;
310
370
case jpiAnd :
@@ -494,12 +554,12 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracket
494
554
if (i )
495
555
appendStringInfoChar (buf , ',' );
496
556
497
- printJsonPathItem (buf , & from , false, false );
557
+ printJsonPathItem (buf , & from , false, from . type == jpiSequence );
498
558
499
559
if (range )
500
560
{
501
561
appendBinaryStringInfo (buf , " to " , 4 );
502
- printJsonPathItem (buf , & to , false, false );
562
+ printJsonPathItem (buf , & to , false, to . type == jpiSequence );
503
563
}
504
564
}
505
565
appendStringInfoChar (buf , ']' );
@@ -563,6 +623,54 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracket
563
623
case jpiKeyValue :
564
624
appendBinaryStringInfo (buf , ".keyvalue()" , 11 );
565
625
break ;
626
+ case jpiSequence :
627
+ if (printBracketes || jspHasNext (v ))
628
+ appendStringInfoChar (buf , '(' );
629
+
630
+ for (i = 0 ; i < v -> content .sequence .nelems ; i ++ )
631
+ {
632
+ JsonPathItem elem ;
633
+
634
+ if (i )
635
+ appendBinaryStringInfo (buf , ", " , 2 );
636
+
637
+ jspGetSequenceElement (v , i , & elem );
638
+
639
+ printJsonPathItem (buf , & elem , false, elem .type == jpiSequence );
640
+ }
641
+
642
+ if (printBracketes || jspHasNext (v ))
643
+ appendStringInfoChar (buf , ')' );
644
+ break ;
645
+ case jpiArray :
646
+ appendStringInfoChar (buf , '[' );
647
+ if (v -> content .arg )
648
+ {
649
+ jspGetArg (v , & elem );
650
+ printJsonPathItem (buf , & elem , false, false);
651
+ }
652
+ appendStringInfoChar (buf , ']' );
653
+ break ;
654
+ case jpiObject :
655
+ appendStringInfoChar (buf , '{' );
656
+
657
+ for (i = 0 ; i < v -> content .object .nfields ; i ++ )
658
+ {
659
+ JsonPathItem key ;
660
+ JsonPathItem val ;
661
+
662
+ jspGetObjectField (v , i , & key , & val );
663
+
664
+ if (i )
665
+ appendBinaryStringInfo (buf , ", " , 2 );
666
+
667
+ printJsonPathItem (buf , & key , false, false);
668
+ appendBinaryStringInfo (buf , ": " , 2 );
669
+ printJsonPathItem (buf , & val , false, val .type == jpiSequence );
670
+ }
671
+
672
+ appendStringInfoChar (buf , '}' );
673
+ break ;
566
674
default :
567
675
elog (ERROR , "Unknown jsonpath item type: %d" , v -> type );
568
676
}
@@ -585,7 +693,7 @@ jsonpath_out(PG_FUNCTION_ARGS)
585
693
appendBinaryStringInfo (& buf , "strict " , 7 );
586
694
587
695
jspInit (& v , in );
588
- printJsonPathItem (& buf , & v , false, true );
696
+ printJsonPathItem (& buf , & v , false, v . type != jpiSequence );
589
697
590
698
PG_RETURN_CSTRING (buf .data );
591
699
}
@@ -688,6 +796,7 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
688
796
case jpiPlus :
689
797
case jpiMinus :
690
798
case jpiFilter :
799
+ case jpiArray :
691
800
read_int32 (v -> content .arg , base , pos );
692
801
break ;
693
802
case jpiIndexArray :
@@ -699,6 +808,16 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
699
808
read_int32 (v -> content .anybounds .first , base , pos );
700
809
read_int32 (v -> content .anybounds .last , base , pos );
701
810
break ;
811
+ case jpiSequence :
812
+ read_int32 (v -> content .sequence .nelems , base , pos );
813
+ read_int32_n (v -> content .sequence .elems , base , pos ,
814
+ v -> content .sequence .nelems );
815
+ break ;
816
+ case jpiObject :
817
+ read_int32 (v -> content .object .nfields , base , pos );
818
+ read_int32_n (v -> content .object .fields , base , pos ,
819
+ v -> content .object .nfields * 2 );
820
+ break ;
702
821
default :
703
822
elog (ERROR , "Unknown jsonpath item type: %d" , v -> type );
704
823
}
@@ -713,7 +832,8 @@ jspGetArg(JsonPathItem *v, JsonPathItem *a)
713
832
v -> type == jpiIsUnknown ||
714
833
v -> type == jpiExists ||
715
834
v -> type == jpiPlus ||
716
- v -> type == jpiMinus
835
+ v -> type == jpiMinus ||
836
+ v -> type == jpiArray
717
837
);
718
838
719
839
jspInitByBuffer (a , v -> base , v -> content .arg );
@@ -765,7 +885,10 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
765
885
v -> type == jpiDouble ||
766
886
v -> type == jpiDatetime ||
767
887
v -> type == jpiKeyValue ||
768
- v -> type == jpiStartsWith
888
+ v -> type == jpiStartsWith ||
889
+ v -> type == jpiSequence ||
890
+ v -> type == jpiArray ||
891
+ v -> type == jpiObject
769
892
);
770
893
771
894
if (a )
@@ -869,3 +992,19 @@ jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to,
869
992
870
993
return true;
871
994
}
995
+
996
+ void
997
+ jspGetSequenceElement (JsonPathItem * v , int i , JsonPathItem * elem )
998
+ {
999
+ Assert (v -> type == jpiSequence );
1000
+
1001
+ jspInitByBuffer (elem , v -> base , v -> content .sequence .elems [i ]);
1002
+ }
1003
+
1004
+ void
1005
+ jspGetObjectField (JsonPathItem * v , int i , JsonPathItem * key , JsonPathItem * val )
1006
+ {
1007
+ Assert (v -> type == jpiObject );
1008
+ jspInitByBuffer (key , v -> base , v -> content .object .fields [i ].key );
1009
+ jspInitByBuffer (val , v -> base , v -> content .object .fields [i ].val );
1010
+ }
0 commit comments