Fix jsonpath .decimal() to honor silent mode

From: Ewan Young <kdbase(dot)hack(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
Subject: Fix jsonpath .decimal() to honor silent mode
Date: 2026-07-01 07:52:51
Message-ID: CAON2xHMaigKABiyPBBq3Sjd3gp7uWMJXnnMHt=s85V1ij3KP1w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi

The jsonpath .decimal() method handles an invalid precision/scale
inconsistently in silent mode,
depending only on which internal check happens to catch it:

-- precision too large for int4: caught softly, suppressed
SELECT jsonb_path_query('1.5', '$.decimal(12345678901)', '{}', true);
jsonb_path_query
------------------
(0 rows)

-- precision in int4 range but outside NUMERIC's 1..1000: hard error
SELECT jsonb_path_query('1.5', '$.decimal(1001)', '{}', true);
ERROR: NUMERIC precision 1001 must be between 1 and 1000

Both are the same kind of mistake (a precision the user cannot use),
both are in silent mode, yet
one returns no rows and the other throws. The same hard error also
escapes the @? and @@ operators,
which are documented to suppress datetime and numeric errors:

SELECT '1.5'::jsonb @? '$.decimal(0)';
ERROR: NUMERIC precision 0 must be between 1 and 1000

.decimal(-1) and .decimal(0) behave like the .decimal(1001) case.

The cause is in executeItemOptUnwrapTarget() (jsonpath_exec.c). The
precision and scale
are converted with numeric_int4_safe() using an ErrorSaveContext, so
an int4-overflowing
precision is reported softly. But the subsequent typmod construction
calls numerictypmodin()
through DirectFunctionCall1() with no ErrorSaveContext, so an
out-of-range NUMERIC
precision/scale throws a hard error that silent mode cannot trap.
Every other error path
in .decimal() (the numeric_int4_safe() conversions and the
numeric_in() value coercion) already
reports softly; only the numerictypmodin() call was left bare. This
dates back to 66ea94e8e606.

This is the same direction taken by 954e57708ea6, which made the
sibling jsonpath .split_part()
method honor silent mode.

The attached patch validates precision and scale against their valid
ranges before calling
numerictypmodin(), reporting any violation via RETURN_ERROR() so
silent mode is honored;
after the pre-check numerictypmodin() can no longer throw. In
non-silent mode the message
becomes method-specific and consistent with the other .decimal() errors:

ERROR: precision of jsonpath item method .decimal() must be between 1 and 1000

If reviewers would rather push the ErrorSaveContext down into
numerictypmodin() (or a shared helper)
instead of pre-validating in the caller, I'm happy to reshape it that way.

--
Regards,
Ewan Young

Attachment Content-Type Size
v1-0001-Fix-jsonpath-decimal-to-honor-silent-mode.patch application/octet-stream 6.5 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Ewan Young 2026-07-01 08:20:39 Re: Prevent crash when calling pgstat functions with unregistered stats kind
Previous Message Henson Choi 2026-07-01 07:49:11 Re: Tighten pg_uhc_verifychar() to enforce CP949 lead/trail byte ranges