2525 */
2626static int
2727flattenJsonPathParseItem (StringInfo buf , JsonPathParseItem * item ,
28- bool forbiddenRoot )
28+ bool forbiddenRoot , bool insideArraySubscript )
2929{
3030 /* position from begining of jsonpath data */
3131 int32 pos = buf -> len - JSONPATH_HDRSZ ;
@@ -88,9 +88,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
8888 right = buf -> len ;
8989 appendBinaryStringInfo (buf , (char * )& right /* fake value */ , sizeof (right ));
9090
91- chld = flattenJsonPathParseItem (buf , item -> value .args .left , forbiddenRoot );
91+ chld = flattenJsonPathParseItem (buf , item -> value .args .left ,
92+ forbiddenRoot ,
93+ insideArraySubscript );
9294 * (int32 * )(buf -> data + left ) = chld ;
93- chld = flattenJsonPathParseItem (buf , item -> value .args .right , forbiddenRoot );
95+ chld = flattenJsonPathParseItem (buf , item -> value .args .right ,
96+ forbiddenRoot ,
97+ insideArraySubscript );
9498 * (int32 * )(buf -> data + right ) = chld ;
9599 }
96100 break ;
@@ -108,7 +112,8 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
108112
109113 chld = flattenJsonPathParseItem (buf , item -> value .arg ,
110114 item -> type == jpiFilter ||
111- forbiddenRoot );
115+ forbiddenRoot ,
116+ insideArraySubscript );
112117 * (int32 * )(buf -> data + arg ) = chld ;
113118 }
114119 break ;
@@ -129,6 +134,12 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
129134 (errcode (ERRCODE_SYNTAX_ERROR ),
130135 errmsg ("@ is not allowed in root expressions" )));
131136 break ;
137+ case jpiLast :
138+ if (!insideArraySubscript )
139+ ereport (ERROR ,
140+ (errcode (ERRCODE_SYNTAX_ERROR ),
141+ errmsg ("LAST is allowed only in array subscripts" )));
142+ break ;
132143 case jpiIndexArray :
133144 {
134145 int32 nelems = item -> value .array .nelems ;
@@ -148,12 +159,12 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
148159 int32 frompos =
149160 flattenJsonPathParseItem (buf ,
150161 item -> value .array .elems [i ].from ,
151- true);
162+ true, true );
152163
153164 if (item -> value .array .elems [i ].to )
154165 topos = flattenJsonPathParseItem (buf ,
155166 item -> value .array .elems [i ].to ,
156- true);
167+ true, true );
157168 else
158169 topos = 0 ;
159170
@@ -187,7 +198,8 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
187198
188199 if (item -> next )
189200 * (int32 * )(buf -> data + next ) =
190- flattenJsonPathParseItem (buf , item -> next , forbiddenRoot );
201+ flattenJsonPathParseItem (buf , item -> next , forbiddenRoot ,
202+ insideArraySubscript );
191203
192204 return pos ;
193205}
@@ -211,7 +223,7 @@ jsonpath_in(PG_FUNCTION_ARGS)
211223 (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
212224 errmsg ("invalid input syntax for jsonpath: \"%s\"" , in )));
213225
214- flattenJsonPathParseItem (& buf , jsonpath -> expr , false);
226+ flattenJsonPathParseItem (& buf , jsonpath -> expr , false, false );
215227
216228 res = (JsonPath * )buf .data ;
217229 SET_VARSIZE (res , buf .len );
@@ -396,6 +408,9 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracket
396408 Assert (!inKey );
397409 appendStringInfoChar (buf , '$' );
398410 break ;
411+ case jpiLast :
412+ appendBinaryStringInfo (buf , "last" , 4 );
413+ break ;
399414 case jpiAnyArray :
400415 appendBinaryStringInfo (buf , "[*]" , 3 );
401416 break ;
@@ -559,6 +574,7 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
559574 case jpiDouble :
560575 case jpiDatetime :
561576 case jpiKeyValue :
577+ case jpiLast :
562578 break ;
563579 case jpiKey :
564580 case jpiString :
@@ -642,6 +658,7 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
642658 v -> type == jpiExists ||
643659 v -> type == jpiRoot ||
644660 v -> type == jpiVariable ||
661+ v -> type == jpiLast ||
645662 v -> type == jpiType ||
646663 v -> type == jpiSize ||
647664 v -> type == jpiAbs ||
0 commit comments