diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c index 8c8422e1e4..13fe196edc 100644 --- a/src/backend/utils/adt/jsonpath_exec.c +++ b/src/backend/utils/adt/jsonpath_exec.c @@ -960,9 +960,13 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *v; bool hasNext = jspGetNext(jsp, &elem); - if (!hasNext && !found) + if (!hasNext && !found && jsp->type != jpiVariable) { - res = jperOk; /* skip evaluation */ + /* + * Skip evaluation, but not for variables. We must + * trigger an error for the missing variable. + */ + res = jperOk; break; } diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out index 508ddd797e..328a6b3919 100644 --- a/src/test/regress/expected/jsonb_jsonpath.out +++ b/src/test/regress/expected/jsonb_jsonpath.out @@ -2212,6 +2212,14 @@ SELECT jsonb_path_query('[{"a": 1}, {"a": 2}]', '$[*] ? (@.a > 10)'); ------------------ (0 rows) +SELECT jsonb_path_query('[{"a": 1}]', '$undefined_var'); +ERROR: could not find jsonpath variable "undefined_var" +SELECT jsonb_path_query('[{"a": 1}]', 'false'); + jsonb_path_query +------------------ + false +(1 row) + SELECT jsonb_path_query_array('[{"a": 1}, {"a": 2}, {}]', 'strict $[*].a'); ERROR: JSON object does not contain key "a" SELECT jsonb_path_query_array('[{"a": 1}, {"a": 2}]', '$[*].a'); @@ -2282,6 +2290,14 @@ SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*]. (1 row) +SELECT jsonb_path_query_first('[{"a": 1}]', '$undefined_var'); +ERROR: could not find jsonpath variable "undefined_var" +SELECT jsonb_path_query_first('[{"a": 1}]', 'false'); + jsonb_path_query_first +------------------------ + false +(1 row) + SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)'; ?column? ---------- @@ -2312,6 +2328,14 @@ SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*] ? (@. f (1 row) +SELECT jsonb_path_exists('[{"a": 1}]', '$undefined_var'); +ERROR: could not find jsonpath variable "undefined_var" +SELECT jsonb_path_exists('[{"a": 1}]', 'false'); + jsonb_path_exists +------------------- + t +(1 row) + SELECT jsonb_path_match('true', '$', silent => false); jsonb_path_match ------------------ @@ -2374,6 +2398,14 @@ SELECT jsonb_path_match('[{"a": 1}, {"a": 2}]', '$[*].a > 1'); t (1 row) +SELECT jsonb_path_match('[{"a": 1}]', '$undefined_var'); +ERROR: could not find jsonpath variable "undefined_var" +SELECT jsonb_path_match('[{"a": 1}]', 'false'); + jsonb_path_match +------------------ + f +(1 row) + -- test string comparison (Unicode codepoint collation) WITH str(j, num) AS ( diff --git a/src/test/regress/sql/jsonb_jsonpath.sql b/src/test/regress/sql/jsonb_jsonpath.sql index 60f73cb059..bd025077d5 100644 --- a/src/test/regress/sql/jsonb_jsonpath.sql +++ b/src/test/regress/sql/jsonb_jsonpath.sql @@ -532,6 +532,8 @@ set time zone default; SELECT jsonb_path_query('[{"a": 1}, {"a": 2}]', '$[*]'); SELECT jsonb_path_query('[{"a": 1}, {"a": 2}]', '$[*] ? (@.a > 10)'); +SELECT jsonb_path_query('[{"a": 1}]', '$undefined_var'); +SELECT jsonb_path_query('[{"a": 1}]', 'false'); SELECT jsonb_path_query_array('[{"a": 1}, {"a": 2}, {}]', 'strict $[*].a'); SELECT jsonb_path_query_array('[{"a": 1}, {"a": 2}]', '$[*].a'); @@ -547,12 +549,16 @@ SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}]', '$[*].a ? (@ == 1)'); SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}]', '$[*].a ? (@ > 10)'); SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*].a ? (@ > $min && @ < $max)', vars => '{"min": 1, "max": 4}'); SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*].a ? (@ > $min && @ < $max)', vars => '{"min": 3, "max": 4}'); +SELECT jsonb_path_query_first('[{"a": 1}]', '$undefined_var'); +SELECT jsonb_path_query_first('[{"a": 1}]', 'false'); SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)'; SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*] ? (@.a > 2)'; SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}]', '$[*].a ? (@ > 1)'); SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*] ? (@.a > $min && @.a < $max)', vars => '{"min": 1, "max": 4}'); SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*] ? (@.a > $min && @.a < $max)', vars => '{"min": 3, "max": 4}'); +SELECT jsonb_path_exists('[{"a": 1}]', '$undefined_var'); +SELECT jsonb_path_exists('[{"a": 1}]', 'false'); SELECT jsonb_path_match('true', '$', silent => false); SELECT jsonb_path_match('false', '$', silent => false); @@ -569,6 +575,8 @@ SELECT jsonb_path_match('[true, true]', '$[*]', silent => false); SELECT jsonb '[{"a": 1}, {"a": 2}]' @@ '$[*].a > 1'; SELECT jsonb '[{"a": 1}, {"a": 2}]' @@ '$[*].a > 2'; SELECT jsonb_path_match('[{"a": 1}, {"a": 2}]', '$[*].a > 1'); +SELECT jsonb_path_match('[{"a": 1}]', '$undefined_var'); +SELECT jsonb_path_match('[{"a": 1}]', 'false'); -- test string comparison (Unicode codepoint collation) WITH str(j, num) AS