Fix jsonpath .split_part() to honor silent mode

The jsonpath .split_part() method passed its field-position argument
through numeric_int4(), that can fail hard if called directly.

This commit switches the code to use numeric_int4_safe() with an error
context for soft reporting, so as the overflow and zero field-position
cases can be handled in silent mode.

Oversight in bd4f879a9c.

Author:  Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Discussion: https://postgr.es/m/FCF996D0-580B-431C-8DE1-A540C58E444C@gmail.com
This commit is contained in:
Michael Paquier 2026-05-14 16:02:07 +09:00
parent 61f8a85a57
commit 954e57708e
3 changed files with 34 additions and 3 deletions

View file

@ -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:

View file

@ -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

View file

@ -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()');