Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b4cc19a

Browse files
committed
Throw error in jsonb_path_match() when result is not single boolean
jsonb_path_match() checks if jsonb document matches jsonpath query. Therefore, jsonpath query should return single boolean. Currently, if result of jsonpath is not a single boolean, NULL is returned independently whether silent mode is on or off. But that appears to be wrong when silent mode is off. This commit makes jsonb_path_match() throw an error in this case. Author: Nikita Glukhov
1 parent 2e64350 commit b4cc19a

File tree

3 files changed

+80
-9
lines changed

3 files changed

+80
-9
lines changed

src/backend/utils/adt/jsonpath_exec.c

+17-9
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,6 @@ jsonb_path_match(PG_FUNCTION_ARGS)
320320
{
321321
Jsonb *jb = PG_GETARG_JSONB_P(0);
322322
JsonPath *jp = PG_GETARG_JSONPATH_P(1);
323-
JsonbValue *jbv;
324323
JsonValueList found = {0};
325324
Jsonb *vars = NULL;
326325
bool silent = true;
@@ -333,18 +332,27 @@ jsonb_path_match(PG_FUNCTION_ARGS)
333332

334333
(void) executeJsonPath(jp, vars, jb, !silent, &found);
335334

336-
if (JsonValueListLength(&found) < 1)
337-
PG_RETURN_NULL();
338-
339-
jbv = JsonValueListHead(&found);
340-
341335
PG_FREE_IF_COPY(jb, 0);
342336
PG_FREE_IF_COPY(jp, 1);
343337

344-
if (jbv->type != jbvBool)
345-
PG_RETURN_NULL();
338+
if (JsonValueListLength(&found) == 1)
339+
{
340+
JsonbValue *jbv = JsonValueListHead(&found);
341+
342+
if (jbv->type == jbvBool)
343+
PG_RETURN_BOOL(jbv->val.boolean);
344+
345+
if (jbv->type == jbvNull)
346+
PG_RETURN_NULL();
347+
}
348+
349+
if (!silent)
350+
ereport(ERROR,
351+
(errcode(ERRCODE_SINGLETON_JSON_ITEM_REQUIRED),
352+
errmsg(ERRMSG_SINGLETON_JSON_ITEM_REQUIRED),
353+
errdetail("expression should return a singleton boolean")));
346354

347-
PG_RETURN_BOOL(jbv->val.boolean);
355+
PG_RETURN_NULL();
348356
}
349357

350358
/*

src/test/regress/expected/jsonb_jsonpath.out

+51
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,57 @@ SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*] ? (@.
17691769
f
17701770
(1 row)
17711771

1772+
SELECT jsonb_path_match('true', '$', silent => false);
1773+
jsonb_path_match
1774+
------------------
1775+
t
1776+
(1 row)
1777+
1778+
SELECT jsonb_path_match('false', '$', silent => false);
1779+
jsonb_path_match
1780+
------------------
1781+
f
1782+
(1 row)
1783+
1784+
SELECT jsonb_path_match('null', '$', silent => false);
1785+
jsonb_path_match
1786+
------------------
1787+
1788+
(1 row)
1789+
1790+
SELECT jsonb_path_match('1', '$', silent => true);
1791+
jsonb_path_match
1792+
------------------
1793+
1794+
(1 row)
1795+
1796+
SELECT jsonb_path_match('1', '$', silent => false);
1797+
ERROR: singleton SQL/JSON item required
1798+
DETAIL: expression should return a singleton boolean
1799+
SELECT jsonb_path_match('"a"', '$', silent => false);
1800+
ERROR: singleton SQL/JSON item required
1801+
DETAIL: expression should return a singleton boolean
1802+
SELECT jsonb_path_match('{}', '$', silent => false);
1803+
ERROR: singleton SQL/JSON item required
1804+
DETAIL: expression should return a singleton boolean
1805+
SELECT jsonb_path_match('[true]', '$', silent => false);
1806+
ERROR: singleton SQL/JSON item required
1807+
DETAIL: expression should return a singleton boolean
1808+
SELECT jsonb_path_match('{}', 'lax $.a', silent => false);
1809+
ERROR: singleton SQL/JSON item required
1810+
DETAIL: expression should return a singleton boolean
1811+
SELECT jsonb_path_match('{}', 'strict $.a', silent => false);
1812+
ERROR: SQL/JSON member not found
1813+
DETAIL: JSON object does not contain key "a"
1814+
SELECT jsonb_path_match('{}', 'strict $.a', silent => true);
1815+
jsonb_path_match
1816+
------------------
1817+
1818+
(1 row)
1819+
1820+
SELECT jsonb_path_match('[true, true]', '$[*]', silent => false);
1821+
ERROR: singleton SQL/JSON item required
1822+
DETAIL: expression should return a singleton boolean
17721823
SELECT jsonb '[{"a": 1}, {"a": 2}]' @@ '$[*].a > 1';
17731824
?column?
17741825
----------

src/test/regress/sql/jsonb_jsonpath.sql

+12
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,18 @@ SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}]', '$[*].a ? (@ > 1)');
366366
SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*] ? (@.a > $min && @.a < $max)', vars => '{"min": 1, "max": 4}');
367367
SELECT jsonb_path_exists('[{"a": 1}, {"a": 2}, {"a": 3}, {"a": 5}]', '$[*] ? (@.a > $min && @.a < $max)', vars => '{"min": 3, "max": 4}');
368368

369+
SELECT jsonb_path_match('true', '$', silent => false);
370+
SELECT jsonb_path_match('false', '$', silent => false);
371+
SELECT jsonb_path_match('null', '$', silent => false);
372+
SELECT jsonb_path_match('1', '$', silent => true);
373+
SELECT jsonb_path_match('1', '$', silent => false);
374+
SELECT jsonb_path_match('"a"', '$', silent => false);
375+
SELECT jsonb_path_match('{}', '$', silent => false);
376+
SELECT jsonb_path_match('[true]', '$', silent => false);
377+
SELECT jsonb_path_match('{}', 'lax $.a', silent => false);
378+
SELECT jsonb_path_match('{}', 'strict $.a', silent => false);
379+
SELECT jsonb_path_match('{}', 'strict $.a', silent => true);
380+
SELECT jsonb_path_match('[true, true]', '$[*]', silent => false);
369381
SELECT jsonb '[{"a": 1}, {"a": 2}]' @@ '$[*].a > 1';
370382
SELECT jsonb '[{"a": 1}, {"a": 2}]' @@ '$[*].a > 2';
371383
SELECT jsonb_path_match('[{"a": 1}, {"a": 2}]', '$[*].a > 1');

0 commit comments

Comments
 (0)