Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit55e4b88

Browse files
author
Nikita Glukhov
committed
Add jsonpath 'pg' modifier for enabling extensions
1 parent079ac29 commit55e4b88

File tree

9 files changed

+116
-20
lines changed

9 files changed

+116
-20
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13663,6 +13663,35 @@ table2-mapping
1366313663

1366413664
</sect3>
1366513665

13666+
<sect3 id="pg-extensions">
13667+
<title>Extensions</title>
13668+
<para>
13669+
<productname>PostgreSQL</productname> has some extensions to the SQL/JSON
13670+
Path standard. These syntax extensions that can enabled by the specifying
13671+
additional <literal>pg</literal> modifier before the
13672+
<literal>strict</literal>/<literal>lax</literal> flags.
13673+
<xref linkend="functions-jsonpath-extensions"/> shows these
13674+
extensions with examples.
13675+
</para>
13676+
13677+
<table id="functions-jsonpath-extensions">
13678+
<title><type>jsonpath</type> Syntax Extensions</title>
13679+
<tgroup cols="5">
13680+
<thead>
13681+
<row>
13682+
<entry>Name</entry>
13683+
<entry>Description</entry>
13684+
<entry>Example JSON</entry>
13685+
<entry>Example JSON path</entry>
13686+
<entry>Result</entry>
13687+
</row>
13688+
</thead>
13689+
<tbody>
13690+
</tbody>
13691+
</tgroup>
13692+
</table>
13693+
</sect3>
13694+
1366613695
<sect3 id="jsonpath-regular-expressions">
1366713696
<title>Regular Expressions</title>
1366813697

‎src/backend/utils/adt/jsonpath.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,20 @@
7272
#include"utils/jsonpath.h"
7373

7474

75+
/* Context for jsonpath encoding. */
76+
typedefstructJsonPathEncodingContext
77+
{
78+
StringInfobuf;/* output buffer */
79+
boolext;/* PG extensions are enabled? */
80+
}JsonPathEncodingContext;
81+
7582
staticDatumjsonPathFromCstring(char*in,intlen);
7683
staticchar*jsonPathToCstring(StringInfoout,JsonPath*in,
7784
intestimated_len);
78-
staticintflattenJsonPathParseItem(StringInfobuf,JsonPathParseItem*item,
79-
intnestingLevel,boolinsideArraySubscript);
85+
staticintflattenJsonPathParseItem(JsonPathEncodingContext*cxt,
86+
JsonPathParseItem*item,
87+
intnestingLevel,
88+
boolinsideArraySubscript);
8089
staticvoidalignStringInfoInt(StringInfobuf);
8190
staticint32reserveSpaceForItemPointer(StringInfobuf);
8291
staticvoidprintJsonPathItem(StringInfobuf,JsonPathItem*v,boolinKey,
@@ -167,6 +176,7 @@ jsonpath_send(PG_FUNCTION_ARGS)
167176
staticDatum
168177
jsonPathFromCstring(char*in,intlen)
169178
{
179+
JsonPathEncodingContextcxt;
170180
JsonPathParseResult*jsonpath=parsejsonpath(in,len);
171181
JsonPath*res;
172182
StringInfoDatabuf;
@@ -182,13 +192,18 @@ jsonPathFromCstring(char *in, int len)
182192
errmsg("invalid input syntax for type %s: \"%s\"","jsonpath",
183193
in)));
184194

185-
flattenJsonPathParseItem(&buf,jsonpath->expr,0, false);
195+
cxt.buf=&buf;
196+
cxt.ext=jsonpath->ext;
197+
198+
flattenJsonPathParseItem(&cxt,jsonpath->expr,0, false);
186199

187200
res= (JsonPath*)buf.data;
188201
SET_VARSIZE(res,buf.len);
189202
res->header=JSONPATH_VERSION;
190203
if (jsonpath->lax)
191204
res->header |=JSONPATH_LAX;
205+
if (jsonpath->ext)
206+
res->header |=JSONPATH_EXT;
192207

193208
PG_RETURN_JSONPATH_P(res);
194209
}
@@ -212,6 +227,8 @@ jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
212227
}
213228
enlargeStringInfo(out,estimated_len);
214229

230+
if (in->header&JSONPATH_EXT)
231+
appendBinaryStringInfo(out,"pg ",3);
215232
if (!(in->header&JSONPATH_LAX))
216233
appendBinaryStringInfo(out,"strict ",7);
217234

@@ -221,14 +238,27 @@ jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
221238
returnout->data;
222239
}
223240

241+
staticvoid
242+
checkJsonPathExtensionsEnabled(JsonPathEncodingContext*cxt,
243+
JsonPathItemTypetype)
244+
{
245+
if (!cxt->ext)
246+
ereport(ERROR,
247+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
248+
errmsg("%s contains extended operators that were not enabled","jsonpath"),
249+
errhint("use \"%s\" modifier at the start of %s string to enable extensions",
250+
"pg","jsonpath")));
251+
}
252+
224253
/*
225254
* Recursive function converting given jsonpath parse item and all its
226255
* children into a binary representation.
227256
*/
228257
staticint
229-
flattenJsonPathParseItem(StringInfobuf,JsonPathParseItem*item,
258+
flattenJsonPathParseItem(JsonPathEncodingContext*cxt,JsonPathParseItem*item,
230259
intnestingLevel,boolinsideArraySubscript)
231260
{
261+
StringInfobuf=cxt->buf;
232262
/* position from beginning of jsonpath data */
233263
int32pos=buf->len-JSONPATH_HDRSZ;
234264
int32chld;
@@ -296,13 +326,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
296326
int32right=reserveSpaceForItemPointer(buf);
297327

298328
chld= !item->value.args.left ?pos :
299-
flattenJsonPathParseItem(buf,item->value.args.left,
329+
flattenJsonPathParseItem(cxt,item->value.args.left,
300330
nestingLevel+argNestingLevel,
301331
insideArraySubscript);
302332
*(int32*) (buf->data+left)=chld-pos;
303333

304334
chld= !item->value.args.right ?pos :
305-
flattenJsonPathParseItem(buf,item->value.args.right,
335+
flattenJsonPathParseItem(cxt,item->value.args.right,
306336
nestingLevel+argNestingLevel,
307337
insideArraySubscript);
308338
*(int32*) (buf->data+right)=chld-pos;
@@ -323,7 +353,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
323353
item->value.like_regex.patternlen);
324354
appendStringInfoChar(buf,'\0');
325355

326-
chld=flattenJsonPathParseItem(buf,item->value.like_regex.expr,
356+
chld=flattenJsonPathParseItem(cxt,item->value.like_regex.expr,
327357
nestingLevel,
328358
insideArraySubscript);
329359
*(int32*) (buf->data+offs)=chld-pos;
@@ -342,7 +372,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
342372
int32arg=reserveSpaceForItemPointer(buf);
343373

344374
chld= !item->value.arg ?pos :
345-
flattenJsonPathParseItem(buf,item->value.arg,
375+
flattenJsonPathParseItem(cxt,item->value.arg,
346376
nestingLevel+argNestingLevel,
347377
insideArraySubscript);
348378
*(int32*) (buf->data+arg)=chld-pos;
@@ -384,12 +414,12 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
384414
int32*ppos;
385415
int32topos;
386416
int32frompos=
387-
flattenJsonPathParseItem(buf,
417+
flattenJsonPathParseItem(cxt,
388418
item->value.array.elems[i].from,
389419
nestingLevel, true)-pos;
390420

391421
if (item->value.array.elems[i].to)
392-
topos=flattenJsonPathParseItem(buf,
422+
topos=flattenJsonPathParseItem(cxt,
393423
item->value.array.elems[i].to,
394424
nestingLevel, true)-pos;
395425
else
@@ -424,7 +454,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
424454

425455
if (item->next)
426456
{
427-
chld=flattenJsonPathParseItem(buf,item->next,nestingLevel,
457+
chld=flattenJsonPathParseItem(cxt,item->next,nestingLevel,
428458
insideArraySubscript)-pos;
429459
*(int32*) (buf->data+next)=chld;
430460
}
@@ -832,7 +862,7 @@ operationPriority(JsonPathItemType op)
832862
void
833863
jspInit(JsonPathItem*v,JsonPath*js)
834864
{
835-
Assert((js->header&~JSONPATH_LAX)==JSONPATH_VERSION);
865+
Assert((js->header&JSONPATH_VERSION_MASK)==JSONPATH_VERSION);
836866
jspInitByBuffer(v,js->data,0);
837867
}
838868

‎src/backend/utils/adt/jsonpath_exec.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ typedef struct JsonPathExecContext
101101
intinnermostArraySize;/* for LAST array index evaluation */
102102
boollaxMode;/* true for "lax" mode, false for "strict"
103103
* mode */
104+
booluseExtensions;/* use PostgreSQL-specific extensions?
105+
* (enabled by 'pg' modifier in jsonpath) */
104106
boolignoreStructuralErrors;/* with "true" structural errors such
105107
* as absence of required json item or
106108
* unexpected json item type are
@@ -157,6 +159,7 @@ typedef struct JsonValueListIterator
157159
#definejspAutoWrap(cxt)((cxt)->laxMode)
158160
#definejspIgnoreStructuralErrors(cxt)((cxt)->ignoreStructuralErrors)
159161
#definejspThrowErrors(cxt)((cxt)->throwErrors)
162+
#definejspUseExtensions(cxt)((cxt)->useExtensions)
160163

161164
/* Convenience macro: return or throw error depending on context */
162165
#defineRETURN_ERROR(throw_error) \
@@ -559,6 +562,7 @@ executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors,
559562

560563
cxt.vars=vars;
561564
cxt.laxMode= (path->header&JSONPATH_LAX)!=0;
565+
cxt.useExtensions= (path->header&JSONPATH_EXT)!=0;
562566
cxt.ignoreStructuralErrors=cxt.laxMode;
563567
cxt.root=&jbv;
564568
cxt.current=&jbv;

‎src/backend/utils/adt/jsonpath_gram.y

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr,
8888
intinteger;
8989
}
9090

91-
%token<str>TO_PNULL_PTRUE_PFALSE_PIS_PUNKNOWN_PEXISTS_P
91+
%token<str>TO_PNULL_PTRUE_PFALSE_PIS_PUNKNOWN_PEXISTS_PPG_P
9292
%token<str>IDENT_PSTRING_PNUMERIC_PINT_PVARIABLE_P
9393
%token<str>OR_PAND_PNOT_P
9494
%token<str>LESS_PLESSEQUAL_PEQUAL_PNOTEQUAL_PGREATEREQUAL_PGREATER_P
@@ -109,7 +109,7 @@ static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr,
109109

110110
%type<optype>comp_opmethod
111111

112-
%type<boolean>mode
112+
%type<boolean>modepg_opt
113113

114114
%type<str>key_name
115115

@@ -127,10 +127,11 @@ static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr,
127127
%%
128128

129129
result:
130-
modeexpr_or_predicate{
130+
pg_optmodeexpr_or_predicate{
131131
*result = palloc(sizeof(JsonPathParseResult));
132-
(*result)->expr =$2;
133-
(*result)->lax =$1;
132+
(*result)->expr =$3;
133+
(*result)->lax =$2;
134+
(*result)->ext =$1;
134135
}
135136
|/* EMPTY*/{ *result =NULL; }
136137
;
@@ -140,6 +141,11 @@ expr_or_predicate:
140141
|predicate{$$ =$1; }
141142
;
142143

144+
pg_opt:
145+
PG_P{$$ =true; }
146+
|/* EMPTY*/{$$ =false; }
147+
;
148+
143149
mode:
144150
STRICT_P{$$ =false; }
145151
|LAX_P{$$ =true; }
@@ -292,6 +298,7 @@ key_name:
292298
|WITH_P
293299
|LIKE_REGEX_P
294300
|FLAG_P
301+
|PG_P
295302
;
296303

297304
method:

‎src/backend/utils/adt/jsonpath_scan.l

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ typedef struct JsonPathKeyword
305305
*/
306306
staticconst JsonPathKeyword keywords[] = {
307307
{2,false,IS_P,"is"},
308+
{2,false,PG_P,"pg"},
308309
{2,false,TO_P,"to"},
309310
{3,false,ABS_P,"abs"},
310311
{3,false,LAX_P,"lax"},

‎src/include/utils/jsonpath.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ typedef struct
2525
chardata[FLEXIBLE_ARRAY_MEMBER];
2626
}JsonPath;
2727

28-
#defineJSONPATH_VERSION(0x01)
29-
#defineJSONPATH_LAX(0x80000000)
28+
#defineJSONPATH_VERSION0x01
29+
#defineJSONPATH_LAX0x80000000/* lax/strict mode */
30+
#defineJSONPATH_EXT0x40000000/* PG extensions */
31+
#defineJSONPATH_VERSION_MASK (~(JSONPATH_LAX | JSONPATH_EXT))
3032
#defineJSONPATH_HDRSZ(offsetof(JsonPath, data))
3133

3234
#defineDatumGetJsonPathP(d)((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM(d)))
@@ -241,7 +243,8 @@ struct JsonPathParseItem
241243
typedefstructJsonPathParseResult
242244
{
243245
JsonPathParseItem*expr;
244-
boollax;
246+
boollax;/* lax/strict mode */
247+
boolext;/* PostgreSQL extensions */
245248
}JsonPathParseResult;
246249

247250
externJsonPathParseResult*parsejsonpath(constchar*str,intlen);

‎src/test/regress/expected/jsonpath.out

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ select 'lax $'::jsonpath;
2121
$
2222
(1 row)
2323

24+
select 'pg $'::jsonpath;
25+
jsonpath
26+
----------
27+
pg $
28+
(1 row)
29+
30+
select 'pg strict $'::jsonpath;
31+
jsonpath
32+
-------------
33+
pg strict $
34+
(1 row)
35+
36+
select 'pg lax $'::jsonpath;
37+
jsonpath
38+
----------
39+
pg $
40+
(1 row)
41+
2442
select '$.a'::jsonpath;
2543
jsonpath
2644
----------

‎src/test/regress/sql/jsonpath.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ select ''::jsonpath;
44
select'$'::jsonpath;
55
select'strict $'::jsonpath;
66
select'lax $'::jsonpath;
7+
select'pg $'::jsonpath;
8+
select'pg strict $'::jsonpath;
9+
select'pg lax $'::jsonpath;
710
select'$.a'::jsonpath;
811
select'$.a.v'::jsonpath;
912
select'$.a.*'::jsonpath;

‎src/tools/pgindent/typedefs.list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,7 @@ JsonLikeRegexContext
11361136
JsonParseContext
11371137
JsonPath
11381138
JsonPathBool
1139+
JsonPathEncodingContext
11391140
JsonPathExecContext
11401141
JsonPathExecResult
11411142
JsonPathGinAddPathItemFunc

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp