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

Commit7247297

Browse files
author
Nikita Glukhov
committed
Allow variable jsonpath specifications
1 parent5070aad commit7247297

File tree

13 files changed

+94
-18
lines changed

13 files changed

+94
-18
lines changed

‎contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3140,7 +3140,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
31403140

31413141
APP_JUMB(jexpr->op);
31423142
JumbleExpr(jstate,jexpr->raw_expr);
3143-
JumbleExpr(jstate,(Node*)jexpr->path_spec);
3143+
JumbleExpr(jstate,jexpr->path_spec);
31443144
foreach(temp,jexpr->passing_names)
31453145
{
31463146
APP_JUMB_STRING(castNode(Value,temp)->val.str);

‎src/backend/executor/execExpr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,6 +2223,13 @@ ExecInitExprRec(Expr *node, ExprState *state,
22232223
&scratch.d.jsonexpr.raw_expr->value,
22242224
&scratch.d.jsonexpr.raw_expr->isnull);
22252225

2226+
scratch.d.jsonexpr.pathspec=
2227+
palloc(sizeof(*scratch.d.jsonexpr.pathspec));
2228+
2229+
ExecInitExprRec((Expr*)jexpr->path_spec,state,
2230+
&scratch.d.jsonexpr.pathspec->value,
2231+
&scratch.d.jsonexpr.pathspec->isnull);
2232+
22262233
scratch.d.jsonexpr.formatted_expr=
22272234
ExecInitExpr((Expr*)jexpr->formatted_expr,state->parent);
22282235

‎src/backend/executor/execExprInterp.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4832,7 +4832,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
48324832
*op->resnull= true;/* until we get a result */
48334833
*op->resvalue= (Datum)0;
48344834

4835-
if (op->d.jsonexpr.raw_expr->isnull)
4835+
if (op->d.jsonexpr.raw_expr->isnull||op->d.jsonexpr.pathspec->isnull)
48364836
{
48374837
/* execute domain checks for NULLs */
48384838
(void)ExecEvalJsonExprCoercion(op,econtext,res,op->resnull);
@@ -4844,8 +4844,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
48444844
}
48454845

48464846
item=op->d.jsonexpr.raw_expr->value;
4847-
4848-
path=DatumGetJsonPathP(jexpr->path_spec->constvalue);
4847+
path=DatumGetJsonPathP(op->d.jsonexpr.pathspec->value);
48494848

48504849
/* reset JSON path variable contexts */
48514850
foreach(lc,op->d.jsonexpr.args)

‎src/backend/nodes/copyfuncs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2565,7 +2565,7 @@ _copyJsonCommon(const JsonCommon *from)
25652565
JsonCommon*newnode=makeNode(JsonCommon);
25662566

25672567
COPY_NODE_FIELD(expr);
2568-
COPY_STRING_FIELD(pathspec);
2568+
COPY_NODE_FIELD(pathspec);
25692569
COPY_STRING_FIELD(pathname);
25702570
COPY_NODE_FIELD(passing);
25712571
COPY_LOCATION_FIELD(location);

‎src/backend/nodes/nodeFuncs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3405,6 +3405,7 @@ expression_tree_mutator(Node *node,
34053405
JsonExpr*newnode;
34063406

34073407
FLATCOPY(newnode,jexpr,JsonExpr);
3408+
MUTATE(newnode->path_spec,jexpr->path_spec,Node*);
34083409
MUTATE(newnode->raw_expr,jexpr->raw_expr,Node*);
34093410
MUTATE(newnode->formatted_expr,jexpr->formatted_expr,Node*);
34103411
MUTATE(newnode->result_coercion,jexpr->result_coercion,JsonCoercion*);
@@ -4264,6 +4265,8 @@ raw_expression_tree_walker(Node *node,
42644265

42654266
if (walker(jc->expr,context))
42664267
return true;
4268+
if (walker(jc->pathspec,context))
4269+
return true;
42674270
if (walker(jc->passing,context))
42684271
return true;
42694272
}

‎src/backend/parser/gram.y

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -629,15 +629,15 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
629629
json_aggregate_func
630630
json_object_aggregate_constructor
631631
json_array_aggregate_constructor
632+
json_path_specification
632633

633634
%type<list>json_name_and_value_list
634635
json_value_expr_list
635636
json_array_aggregate_order_by_clause_opt
636637
json_arguments
637638
json_passing_clause_opt
638639

639-
%type<str>json_path_specification
640-
json_table_path_name
640+
%type<str>json_table_path_name
641641
json_as_path_name_clause_opt
642642

643643
%type<ival>json_encoding
@@ -843,6 +843,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
843843
*/
844844
%nonassocUNBOUNDED/* ideally should have same precedence as IDENT*/
845845
%nonassocERROR_PEMPTY_PDEFAULTABSENT/* JSON error/empty behavior*/
846+
%nonassocFALSE_PKEEPOMITPASSINGTRUE_PUNKNOWN
846847
%nonassocIDENTGENERATEDNULL_PPARTITIONRANGEROWSGROUPSPRECEDINGFOLLOWINGCUBEROLLUP
847848
%leftOpOPERATOR/* multi-character ops and user-defined operators*/
848849
%left'+''-'
@@ -14831,7 +14832,7 @@ json_context_item:
1483114832
;
1483214833

1483314834
json_path_specification:
14834-
Sconst{ $$ = $1; }
14835+
a_expr{ $$ = $1; }
1483514836
;
1483614837

1483714838
json_as_path_name_clause_opt:

‎src/backend/parser/parse_expr.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4535,7 +4535,7 @@ static JsonExpr *
45354535
transformJsonExprCommon(ParseState*pstate,JsonFuncExpr*func)
45364536
{
45374537
JsonExpr*jsexpr=makeNode(JsonExpr);
4538-
Datumjsonpath;
4538+
Node*pathspec;
45394539
JsonFormatTypeformat;
45404540

45414541
if (func->common->pathname)
@@ -4566,12 +4566,19 @@ transformJsonExprCommon(ParseState *pstate, JsonFuncExpr *func)
45664566

45674567
jsexpr->format=func->common->expr->format;
45684568

4569-
/* parse JSON path string */
4570-
jsonpath=DirectFunctionCall1(jsonpath_in,
4571-
CStringGetDatum(func->common->pathspec));
4569+
pathspec=transformExprRecurse(pstate,func->common->pathspec);
45724570

4573-
jsexpr->path_spec=makeConst(JSONPATHOID,-1,InvalidOid,-1,
4574-
jsonpath, false, false);
4571+
jsexpr->path_spec=
4572+
coerce_to_target_type(pstate,pathspec,exprType(pathspec),
4573+
JSONPATHOID,-1,
4574+
COERCION_EXPLICIT,COERCE_IMPLICIT_CAST,
4575+
exprLocation(pathspec));
4576+
if (!jsexpr->path_spec)
4577+
ereport(ERROR,
4578+
(errcode(ERRCODE_DATATYPE_MISMATCH),
4579+
errmsg("JSON path expression must be type %s, not type %s",
4580+
"jsonpath",format_type_be(exprType(pathspec))),
4581+
parser_errposition(pstate,exprLocation(pathspec))));
45754582

45764583
/* transform and coerce to json[b] passing arguments */
45774584
transformJsonPassingArgs(pstate,format,func->common->passing,

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ static char *generate_qualified_type_name(Oid typid);
487487
statictext*string_to_text(char*str);
488488
staticchar*flatten_reloptions(Oidrelid);
489489
staticvoidget_reloptions(StringInfobuf,Datumreloptions);
490+
staticvoidget_json_path_spec(Node*path_spec,deparse_context*context,
491+
boolshowimplicit);
490492

491493
#defineonly_marker(rte) ((rte)->inh ? "" : "ONLY ")
492494

@@ -7909,6 +7911,19 @@ get_rule_expr_paren(Node *node, deparse_context *context,
79097911
appendStringInfoChar(context->buf,')');
79107912
}
79117913

7914+
7915+
/*
7916+
* get_json_path_spec- Parse back a JSON path specification
7917+
*/
7918+
staticvoid
7919+
get_json_path_spec(Node*path_spec,deparse_context*context,boolshowimplicit)
7920+
{
7921+
if (IsA(path_spec,Const))
7922+
get_const_expr((Const*)path_spec,context,-1);
7923+
else
7924+
get_rule_expr(path_spec,context,showimplicit);
7925+
}
7926+
79127927
/*
79137928
* get_json_format- Parse back a JsonFormat node
79147929
*/
@@ -9271,7 +9286,7 @@ get_rule_expr(Node *node, deparse_context *context,
92719286

92729287
appendStringInfoString(buf,", ");
92739288

9274-
get_const_expr(jexpr->path_spec,context,-1);
9289+
get_json_path_spec(jexpr->path_spec,context,showimplicit);
92759290

92769291
if (jexpr->passing_values)
92779292
{

‎src/include/executor/execExpr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,8 @@ typedef struct ExprEvalStep
676676
{
677677
Datumvalue;
678678
boolisnull;
679-
}*raw_expr;/* raw context item value */
679+
}*raw_expr,/* raw context item value */
680+
*pathspec;/* path specification value */
680681

681682
ExprState*formatted_expr;/* formatted context item */
682683
ExprState*result_expr;/* coerced to output type */

‎src/include/nodes/parsenodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1535,7 +1535,7 @@ typedef struct JsonCommon
15351535
{
15361536
NodeTagtype;
15371537
JsonValueExpr*expr;/* context item expression */
1538-
JsonPathSpecpathspec;/* JSON path specification */
1538+
Node*pathspec;/* JSON path specification expression */
15391539
char*pathname;/* path name, if any */
15401540
List*passing;/* list of PASSING clause arguments, if any */
15411541
intlocation;/* token location, or -1 if unknown */

‎src/include/nodes/primnodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1394,7 +1394,7 @@ typedef struct JsonExpr
13941394
Node*formatted_expr;/* formatted context item expression */
13951395
JsonCoercion*result_coercion;/* resulting coercion to RETURNING type */
13961396
JsonFormat*format;/* context item format (JSON/JSONB) */
1397-
Const*path_spec;/* JSON path specification */
1397+
Node*path_spec;/* JSON path specification expression */
13981398
List*passing_names;/* PASSING argument names */
13991399
List*passing_values;/* PASSING argument values */
14001400
JsonReturning*returning;/* RETURNING clause type/format info */

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,3 +875,37 @@ INSERT INTO test_jsonb_constraints VALUES ('{"a": 10}', 1);
875875
ERROR: new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint4"
876876
DETAIL: Failing row contains ({"a": 10}, 1, [1, 2]).
877877
DROP TABLE test_jsonb_constraints;
878+
-- Extension: non-constant JSON path
879+
SELECT JSON_EXISTS(jsonb '{"a": 123}', '$' || '.' || 'a');
880+
json_exists
881+
-------------
882+
t
883+
(1 row)
884+
885+
SELECT JSON_VALUE(jsonb '{"a": 123}', '$' || '.' || 'a');
886+
json_value
887+
------------
888+
123
889+
(1 row)
890+
891+
SELECT JSON_VALUE(jsonb '{"a": 123}', '$' || '.' || 'b' DEFAULT 'foo' ON EMPTY);
892+
json_value
893+
------------
894+
foo
895+
(1 row)
896+
897+
SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a');
898+
json_query
899+
------------
900+
123
901+
(1 row)
902+
903+
SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
904+
json_query
905+
------------
906+
[123]
907+
(1 row)
908+
909+
-- Should fail (invalid path)
910+
SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
911+
ERROR: syntax error, unexpected IDENT_P at or near " " of jsonpath input

‎src/test/regress/sql/jsonb_sqljson.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,12 @@ INSERT INTO test_jsonb_constraints VALUES ('{"a": 7}', 1);
265265
INSERT INTO test_jsonb_constraintsVALUES ('{"a": 10}',1);
266266

267267
DROPTABLE test_jsonb_constraints;
268+
269+
-- Extension: non-constant JSON path
270+
SELECT JSON_EXISTS(jsonb'{"a": 123}','$'||'.'||'a');
271+
SELECT JSON_VALUE(jsonb'{"a": 123}','$'||'.'||'a');
272+
SELECT JSON_VALUE(jsonb'{"a": 123}','$'||'.'||'b' DEFAULT'foo'ON EMPTY);
273+
SELECT JSON_QUERY(jsonb'{"a": 123}','$'||'.'||'a');
274+
SELECT JSON_QUERY(jsonb'{"a": 123}','$'||'.'||'a' WITH WRAPPER);
275+
-- Should fail (invalid path)
276+
SELECT JSON_QUERY(jsonb'{"a": 123}','error'||''||'error');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp