Skip to content

JSON_TABLE: table => column ON ERROR propagation - #406

Open
pg-hub-mirror[bot] wants to merge 1 commit into
masterfrom
pg-hub/mirror-patch-b954122250b5efde
Open

pg-hub-mirror[bot] wants to merge 1 commit into
masterfrom
pg-hub/mirror-patch-b954122250b5efde

Conversation

@pg-hub-mirror

@pg-hub-mirror pg-hub-mirror Bot commented Sep 17, 2026

Copy link
Copy Markdown

Read-only mirror. Reply and review on pgsql-hackers; activity here is not sent upstream.

  • Original author: Alexander Korotkov <aekorotkov(at)gmail(dot)com>
  • Mailing list: pgsql-hackers
  • Message-ID: CAPpHfduc7vM5h8U6XA7-hn0GWRGP5Xc4QXL3u=U-b1_=ujjHfg@mail.gmail.com
  • Original email

Patch files:


On Wed, Aug 12, 2026 at 2:44 PM Alexander Korotkov <aekorotkov(at)gmail(dot)com> wrote:

On Fri, Aug 7, 2026 at 8:00 AM Nikita Malakhov <hukutoc(at)gmail(dot)com> wrote:

Alexander, IMHO the 2nd option is the best. To revise queries for 2 versions
could involve a lot of work, testing and system behavior changes.

Thank you for your feedback. Any other opinions?
Hearing nothing back I suppose we should go with option 2: master
only, release note for v20.
Reasons, with the precedents I checked:

  • Nothing is silently wrong in 17-19: the table-level clause is
    ignored for columns consistently, and the result is the NULL an
    explicit NULL ON ERROR would give. Compare 4c75cc7, which we did
    back-patch into 17 long after GA: there RETURNING numeric(4,1) DEFAULT
    99999.999 returned a value the type itself rejects, and it could be
    stored into a numeric(4,1) column. We back-patch when the old
    behavior yields results no correct query could want, not when it is
    just non-conforming.
  • We documented the current behavior in 17 -- "this clause does not
    affect the errors that occur when evaluating columns". We are
    retracting a promise, not fixing an undocumented accident.
  • 9321d2f is the closest structural precedent that went to a next
    major release only. It changed foreign key collation handling after
    the standard's own rule turned out to be wrong. The new rule rejects
    schemas that used to be valid, and that is exactly why it was put to
    v18: users meet it at a major upgrade, where reading the notes and
    adjusting is part of the job. Ours is milder, and fits the same
    placement.
  • Our change is quite small: only queries with a table-level ERROR ON
    ERROR that rely on columns still returning NULL. Without it, or with
    explicit per-column clauses, nothing changes.
    v2 attached; code unchanged from v1, the commit message records the
    above. Suggested release note: a JSON_TABLE column without its own ON
    ERROR clause now inherits ERROR ON ERROR from the table-level clause;
    add an explicit NULL ON ERROR to keep the old behavior.
    I'm going to push this to master if no objections.

Regards,
Alexander Korotkov
Supabase

Per ISO/IEC 9075-2:2023, 7.11 <JSON table>, Syntax Rules 1)e)iv) and
1)f)xi), a regular or formatted JSON_TABLE column that does not specify
its own ON ERROR clause inherits its default error behavior from the
table-level ON ERROR clause: when the table specifies ERROR ON ERROR, the
column's implicit behavior is ERROR ON ERROR; otherwise (table-level
EMPTY, which is also the default) the column defaults to NULL ON ERROR.

PostgreSQL instead always defaulted such columns to NULL ON ERROR,
ignoring the table-level ERROR ON ERROR.  For example

  SELECT * FROM JSON_TABLE(jsonb '"err"', '$'
                           COLUMNS (a int PATH '$') ERROR ON ERROR) jt;

returned a NULL row where the standard requires an error to be raised.
The documentation even stated that the table-level clause "does not
affect the errors that occur when evaluating columns".

Implement the standard behavior at the JSON_TABLE syntactic
transformation: when a column lacks its own ON ERROR clause and the
table-level behavior is ERROR ON ERROR, synthesize an implicit ERROR ON
ERROR for the column before it is transformed into a JsonExpr.  A column
with its own ON ERROR clause is unaffected.  EXISTS columns are not part
of the standard, so they keep their FALSE ON ERROR default.

Update the documentation and regression tests accordingly; existing
tests that asserted the non-conforming behavior now assert the
propagation.  Note that a JSON_TABLE stored in a view is now deparsed
with the (previously implicit) ERROR ON ERROR shown explicitly on the
affected columns, which is a semantically equivalent, round-trip-stable
form.

Discussion: https://postgr.es/m/CAPpHfdt%3DLncQH9PAq9O8qO7KZcTT9rOsxLLanscRF7xDFvK8mA%40mail.gmail.com
@pg-hub-mirror pg-hub-mirror Bot added source:pgsql-hackers Mirrored from pgsql-hackers type:patch Mail thread contains a PostgreSQL patch area:testing Tests and buildfarm labels Sep 17, 2026
@pg-hub-mirror pg-hub-mirror Bot locked and limited conversation to collaborators Sep 17, 2026
@pg-hub-mirror pg-hub-mirror Bot unlocked this conversation Sep 19, 2026
@pg-hub-mirror

pg-hub-mirror Bot commented Sep 19, 2026

Copy link
Copy Markdown
Author

Alexander Korotkov <aekorotkov(at)gmail(dot)com> via pgsql-hackers · original email

On Thu, Sep 17, 2026 at 5:09 PM Alexander Korotkov <aekorotkov(at)gmail(dot)com> wrote:

On Wed, Aug 12, 2026 at 2:44 PM Alexander Korotkov <aekorotkov(at)gmail(dot)com> wrote:

On Fri, Aug 7, 2026 at 8:00 AM Nikita Malakhov <hukutoc(at)gmail(dot)com> wrote:

Alexander, IMHO the 2nd option is the best. To revise queries for 2 versions
could involve a lot of work, testing and system behavior changes.

Thank you for your feedback. Any other opinions?

Hearing nothing back I suppose we should go with option 2: master
only, release note for v20.

Reasons, with the precedents I checked:

  • Nothing is silently wrong in 17-19: the table-level clause is
    ignored for columns consistently, and the result is the NULL an
    explicit NULL ON ERROR would give. Compare 4c75cc7, which we did
    back-patch into 17 long after GA: there RETURNING numeric(4,1) DEFAULT
    99999.999 returned a value the type itself rejects, and it could be
    stored into a numeric(4,1) column. We back-patch when the old
    behavior yields results no correct query could want, not when it is
    just non-conforming.

  • We documented the current behavior in 17 -- "this clause does not
    affect the errors that occur when evaluating columns". We are
    retracting a promise, not fixing an undocumented accident.

  • 9321d2f is the closest structural precedent that went to a next
    major release only. It changed foreign key collation handling after
    the standard's own rule turned out to be wrong. The new rule rejects
    schemas that used to be valid, and that is exactly why it was put to
    v18: users meet it at a major upgrade, where reading the notes and
    adjusting is part of the job. Ours is milder, and fits the same
    placement.

  • Our change is quite small: only queries with a table-level ERROR ON
    ERROR that rely on columns still returning NULL. Without it, or with
    explicit per-column clauses, nothing changes.

v2 attached; code unchanged from v1, the commit message records the
above. Suggested release note: a JSON_TABLE column without its own ON
ERROR clause now inherits ERROR ON ERROR from the table-level clause;
add an explicit NULL ON ERROR to keep the old behavior.

I'm going to push this to master if no objections.
Pushed.


Regards,
Alexander Korotkov
Supabase

@pg-hub-mirror pg-hub-mirror Bot locked and limited conversation to collaborators Sep 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area:testing Tests and buildfarm source:pgsql-hackers Mirrored from pgsql-hackers type:patch Mail thread contains a PostgreSQL patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant