Skip to content

Commit b5511fe

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 2fc5c50 commit b5511fe

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
@@ -4273,6 +4273,9 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
42734273
{
42744274
JsonExpr *jsexpr;
42754275
Node *path_spec;
4276+
Oid pathspec_type;
4277+
int pathspec_loc;
4278+
Node *coerced_path_spec;
42764279
const char *func_name = NULL;
42774280
JsonFormatType default_format;
42784281

@@ -4488,17 +4491,21 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
44884491
jsexpr->format = func->context_item->format;
44894492

44904493
path_spec = transformExprRecurse(pstate, func->pathspec);
4491-
path_spec = coerce_to_target_type(pstate, path_spec, exprType(path_spec),
4492-
JSONPATHOID, -1,
4493-
COERCION_EXPLICIT, COERCE_IMPLICIT_CAST,
4494-
exprLocation(path_spec));
4495-
if (path_spec == NULL)
4494+
pathspec_type = exprType(path_spec);
4495+
pathspec_loc = exprLocation(path_spec);
4496+
coerced_path_spec = coerce_to_target_type(pstate, path_spec,
4497+
pathspec_type,
4498+
JSONPATHOID, -1,
4499+
COERCION_EXPLICIT,
4500+
COERCE_IMPLICIT_CAST,
4501+
pathspec_loc);
4502+
if (coerced_path_spec == NULL)
44964503
ereport(ERROR,
44974504
(errcode(ERRCODE_DATATYPE_MISMATCH),
44984505
errmsg("JSON path expression must be of type %s, not of type %s",
4499-
"jsonpath", format_type_be(exprType(path_spec))),
4500-
parser_errposition(pstate, exprLocation(path_spec))));
4501-
jsexpr->path_spec = path_spec;
4506+
"jsonpath", format_type_be(pathspec_type)),
4507+
parser_errposition(pstate, pathspec_loc)));
4508+
jsexpr->path_spec = coerced_path_spec;
45024509

45034510
/* Transform and coerce the PASSING arguments to jsonb. */
45044511
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)