Skip to content

Commit 519fa04

Browse files
committed
Fix error reporting for SQL/JSON path type mismatches
transformJsonFuncExpr() used exprType()/exprLocation() on the possibly coerced path expression, which could be NULL when coercion to jsonpath failed, leading to "cache lookup failed for type 0" errors. Preserve the original expression node so that type and location in the "must be of type jsonpath" error are reported correctly. Add regression tests to cover these cases. Reported-by: Jian He <jian.universality@gmail.com> Author: Jian He <jian.universality@gmail.com> Reviewed-by: Kirill Reshke <reshkekirill@gmail.com> Discussion: https://postgr.es/m/CACJufxHunVg81JMuNo8Yvv_hJD0DicgaVN2Wteu8aJbVJPBjZA@mail.gmail.com Backpatch-through: 17
1 parent 0ca3b16 commit 519fa04

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

src/backend/parser/parse_expr.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4285,6 +4285,9 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
42854285
{
42864286
JsonExpr *jsexpr;
42874287
Node *path_spec;
4288+
Oid pathspec_type;
4289+
int pathspec_loc;
4290+
Node *coerced_path_spec;
42884291
const char *func_name = NULL;
42894292
JsonFormatType default_format;
42904293

@@ -4500,17 +4503,21 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
45004503
jsexpr->format = func->context_item->format;
45014504

45024505
path_spec = transformExprRecurse(pstate, func->pathspec);
4503-
path_spec = coerce_to_target_type(pstate, path_spec, exprType(path_spec),
4504-
JSONPATHOID, -1,
4505-
COERCION_EXPLICIT, COERCE_IMPLICIT_CAST,
4506-
exprLocation(path_spec));
4507-
if (path_spec == NULL)
4506+
pathspec_type = exprType(path_spec);
4507+
pathspec_loc = exprLocation(path_spec);
4508+
coerced_path_spec = coerce_to_target_type(pstate, path_spec,
4509+
pathspec_type,
4510+
JSONPATHOID, -1,
4511+
COERCION_EXPLICIT,
4512+
COERCE_IMPLICIT_CAST,
4513+
pathspec_loc);
4514+
if (coerced_path_spec == NULL)
45084515
ereport(ERROR,
45094516
(errcode(ERRCODE_DATATYPE_MISMATCH),
45104517
errmsg("JSON path expression must be of type %s, not of type %s",
4511-
"jsonpath", format_type_be(exprType(path_spec))),
4512-
parser_errposition(pstate, exprLocation(path_spec))));
4513-
jsexpr->path_spec = path_spec;
4518+
"jsonpath", format_type_be(pathspec_type)),
4519+
parser_errposition(pstate, pathspec_loc)));
4520+
jsexpr->path_spec = coerced_path_spec;
45144521

45154522
/* Transform and coerce the PASSING arguments to jsonb. */
45164523
transformJsonPassingArgs(pstate, func_name,

src/test/regress/expected/sqljson_queryfuncs.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,10 @@ SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
13311331
[123]
13321332
(1 row)
13331333

1334+
SELECT JSON_QUERY(jsonb '{"a": 123}', ('$' || '.' || 'a' || NULL)::date WITH WRAPPER);
1335+
ERROR: JSON path expression must be of type jsonpath, not of type date
1336+
LINE 1: SELECT JSON_QUERY(jsonb '{"a": 123}', ('$' || '.' || 'a' || ...
1337+
^
13341338
-- Should fail (invalid path)
13351339
SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
13361340
ERROR: syntax error at or near " " of jsonpath input
@@ -1355,6 +1359,10 @@ SELECT json_value('"aaa"', path RETURNING json) FROM jsonpaths;
13551359
"aaa"
13561360
(1 row)
13571361

1362+
SELECT json_value('"aaa"', jsonpaths RETURNING json) FROM jsonpaths;
1363+
ERROR: JSON path expression must be of type jsonpath, not of type jsonpaths
1364+
LINE 1: SELECT json_value('"aaa"', jsonpaths RETURNING json) FROM js...
1365+
^
13581366
-- Test PASSING argument parsing
13591367
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xy);
13601368
ERROR: could not find jsonpath variable "xyz"

src/test/regress/sql/sqljson_queryfuncs.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ SELECT JSON_VALUE(jsonb '{"a": 123}', '$' || '.' || 'a');
450450
SELECT JSON_VALUE(jsonb '{"a": 123}', '$' || '.' || 'b' DEFAULT 'foo' ON EMPTY);
451451
SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a');
452452
SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
453+
SELECT JSON_QUERY(jsonb '{"a": 123}', ('$' || '.' || 'a' || NULL)::date WITH WRAPPER);
453454
-- Should fail (invalid path)
454455
SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
455456

@@ -460,6 +461,7 @@ SELECT JSON_QUERY(NULL FORMAT JSON, '$');
460461
-- Test non-const jsonpath
461462
CREATE TEMP TABLE jsonpaths (path) AS SELECT '$';
462463
SELECT json_value('"aaa"', path RETURNING json) FROM jsonpaths;
464+
SELECT json_value('"aaa"', jsonpaths RETURNING json) FROM jsonpaths;
463465

464466
-- Test PASSING argument parsing
465467
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xy);

0 commit comments

Comments
 (0)