Re: Casts from jsonb to other types should cope with json null

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Maxim Orlov <orlovmg(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Maciek Sakrejda <maciek(at)pganalyze(dot)com>, "pgsql-hackers(at)lists(dot)postgresql(dot)org" <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Casts from jsonb to other types should cope with json null
Date: 2025-01-24 19:20:34
Message-ID: 516618.1737746434@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I wrote:
> OK. Nobody has spoken against the 0001 patch (replace errors with
> return-a-null), so I think I'll go ahead and commit that one.
> Then I'll return to this thread with a fleshed-out patch for 0002.

0001 is pushed, and as promised, here's a version of 0002 extended
to cover all the string-category types.

However ... the more I play with 0002, the less enchanted I get.
The problem is that there are two different use-cases to serve:

1. General conversion of any jsonb value to string form.
2. Conversion of a jsonb scalar string to a SQL string.

For use-case #1, it makes sense that we do

regression=# select '"hello"'::jsonb::text;
text
---------
"hello"
(1 row)

but for use-case #2, you'd probably prefer that the quotes
weren't included. (We can't do that in use-case #1 because
the string contents might look too much like some other
sort of JSON value.) So it seems like two separate conversion
functions are needed to serve these two use-cases, and for
better or worse we've already decided that casting jsonb to text
is meant for use-case #1. (It was sort of a decision by default,
I suspect, but not deciding is still a decision.)

What I am realizing is that "JSON null becomes SQL NULL" is a rule
that is adapted to use-case #2 but not so much to use-case #1.
For example, the existing behavior

regression=# select null::jsonb::text;
text
------

(1 row)

regression=# select 'null'::jsonb::text;
text
------
null
(1 row)

actually makes plenty of sense if you hope to be able to round-trip
the result. It's only after rejecting non-scalar JSON values that
it makes sense to special-case a JSON null.

So here's the patch, just because I promised it, but I'm now
thinking about withdrawing it.

What would make more sense for use-case #2 is something that
produces NULL for JSON null, a de-quoted string for a JSON
string value, and an error otherwise. The ->> operator is
about halfway there (it won't throw an error for non-scalar
input), but of course that only works when the value you want
to extract is in a JSON object field. I guess what would
be wanted is a new function f(jsonb) returns text, but I'm
unsure about a good name.

regards, tom lane

Attachment Content-Type Size
v2-0002-Make-jsonb-cast-to-text-translate-JSON-null-to-SQ.patch text/x-diff 6.6 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Andres Freund 2025-01-24 19:23:26 Re: BF member drongo doesn't like 035_standby_logical_decoding.pl
Previous Message Masahiko Sawada 2025-01-24 19:16:18 Re: POC: enable logical decoding when wal_level = 'replica' without a server restart