public inbox for [email protected]
help / color / mirror / Atom feedFrom: Chao Li <[email protected]>
To: PostgreSQL Hackers <[email protected]>
Cc: Florents Tselai <[email protected]>
Cc: Andrew Dunstan <[email protected]>
Subject: Fix jsonpath .split_part() to honor silent mode
Date: Tue, 12 May 2026 10:10:53 +0800
Message-ID: <[email protected]> (raw)
Hi,
While testing the new json_path method split_part(), I noticed that it doesn’t honor silent mode. I think this is a v19-new bug.
This is a simple repro:
```
evantest=# select jsonb_path_query('"a,b"', '$.split_part(",", 0)');
ERROR: field position must not be zero
evantest=# select jsonb_path_query('"a,b"', '$.split_part(",", 0)', silent => true);
ERROR: field position must not be zero
evantest=# select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)');
ERROR: integer out of range
evantest=# select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)', silent => true);
ERROR: integer out of range
```
As a comparison, an existing method such as .decimal() suppresses similar argument errors in silent mode:
```
evantest=# select jsonb_path_query('12.3', '$.decimal(12345678901,1)');
ERROR: precision of jsonpath item method .decimal() is out of range for type integer
evantest=# select jsonb_path_query('12.3', '$.decimal(12345678901,1)', silent => true);
jsonb_path_query
------------------
(0 rows)
```
After looking into the code, I think the root cause is that .decimal() uses numeric_int4_safe() to parse integer arguments, while the .split_part() path in executeStringInternalMethod() uses numeric_int4() directly, which raises an error immediately for invalid values.
The attached patch fixes this by switching the .split_part() path to use numeric_int4_safe() and report the argument errors through the jsonpath error handling mechanism.
Please see the attached patch for details.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
Attachments:
[application/octet-stream] v1-0001-Fix-jsonpath-.split_part-to-honor-silent-mode.patch (4.7K, 2-v1-0001-Fix-jsonpath-.split_part-to-honor-silent-mode.patch)
download | inline diff:
From f75ae350b7a1b3398cffda315d00943890c92292 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <[email protected]>
Date: Tue, 12 May 2026 09:54:35 +0800
Subject: [PATCH v1] Fix jsonpath .split_part() to honor silent mode
The jsonpath .split_part() method passed its field-position argument
through numeric_int4() and then called split_part() directly. As a
result, int4 overflow and zero field-position errors were thrown outside
jsonpath's RETURN_ERROR() path, so they were not suppressed when
jsonpath functions were called with silent => true.
Fix this by converting the numeric argument with numeric_int4_safe() and
checking for a zero field position in jsonpath_exec.c, reporting both
errors through RETURN_ERROR().
Add regression tests for zero and out-of-range field positions, including
silent mode.
Author: Chao Li <[email protected]>
Reviewed-by:
Discussion: https://postgr.es/m/
---
src/backend/utils/adt/jsonpath_exec.c | 19 ++++++++++++++++---
src/test/regress/expected/jsonb_jsonpath.out | 14 ++++++++++++++
src/test/regress/sql/jsonb_jsonpath.sql | 4 ++++
3 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 0ec9b4df2ef..6cc2acb4254 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -3017,7 +3017,8 @@ executeStringInternalMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
case jpiStrSplitPart:
{
char *from_str;
- Numeric n;
+ int32 n;
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
jspGetLeftArg(jsp, &elem);
if (elem.type != jpiString)
@@ -3029,13 +3030,25 @@ executeStringInternalMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
if (elem.type != jpiNumeric)
elog(ERROR, "invalid jsonpath item type for .split_part()");
- n = jspGetNumeric(&elem);
+ n = numeric_int4_safe(jspGetNumeric(&elem),
+ (Node *) &escontext);
+ if (escontext.error_occurred)
+ RETURN_ERROR(ereport(ERROR,
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("field position of jsonpath item method .%s() is out of range for type integer",
+ jspOperationName(jsp->type))));
+
+ if (n == 0)
+ RETURN_ERROR(ereport(ERROR,
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("field position of jsonpath item method .%s() must not be zero",
+ jspOperationName(jsp->type))));
resStr = TextDatumGetCString(DirectFunctionCall3Coll(split_part,
DEFAULT_COLLATION_OID,
str,
CStringGetTextDatum(from_str),
- DirectFunctionCall1(numeric_int4, NumericGetDatum(n))));
+ Int32GetDatum(n)));
break;
}
default:
diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out
index afa6c4cb529..81efebc3d0f 100644
--- a/src/test/regress/expected/jsonb_jsonpath.out
+++ b/src/test/regress/expected/jsonb_jsonpath.out
@@ -3073,6 +3073,20 @@ select jsonb_path_query('"abc,def,ghi,jkl"', '$.split_part(",", -2)');
"ghi"
(1 row)
+select jsonb_path_query('"a,b"', '$.split_part(",", 0)');
+ERROR: field position of jsonpath item method .split_part() must not be zero
+select jsonb_path_query('"a,b"', '$.split_part(",", 0)', silent => true);
+ jsonb_path_query
+------------------
+(0 rows)
+
+select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)');
+ERROR: field position of jsonpath item method .split_part() is out of range for type integer
+select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)', silent => true);
+ jsonb_path_query
+------------------
+(0 rows)
+
-- Test string methods play nicely together
select jsonb_path_query('"hello world"', '$.replace("hello","bye").upper()');
jsonb_path_query
diff --git a/src/test/regress/sql/jsonb_jsonpath.sql b/src/test/regress/sql/jsonb_jsonpath.sql
index d3a38c57791..c1f4ab5422e 100644
--- a/src/test/regress/sql/jsonb_jsonpath.sql
+++ b/src/test/regress/sql/jsonb_jsonpath.sql
@@ -721,6 +721,10 @@ select jsonb_path_query('"hello world"', '$.replace("hello","bye") starts with "
-- Test .split_part()
select jsonb_path_query('"abc~@~def~@~ghi"', '$.split_part("~@~", 2)');
select jsonb_path_query('"abc,def,ghi,jkl"', '$.split_part(",", -2)');
+select jsonb_path_query('"a,b"', '$.split_part(",", 0)');
+select jsonb_path_query('"a,b"', '$.split_part(",", 0)', silent => true);
+select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)');
+select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)', silent => true);
-- Test string methods play nicely together
select jsonb_path_query('"hello world"', '$.replace("hello","bye").upper()');
--
2.50.1 (Apple Git-155)
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected]
Subject: Re: Fix jsonpath .split_part() to honor silent mode
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox