Обсуждение: Inconsistent Behavior in JSONB Numeric Array Deletion

Поиск
Список
Период
Сортировка

Inconsistent Behavior in JSONB Numeric Array Deletion

От
"Mark Dake"
Дата:

Hi all,

I’d like to report what I believe is an inconsistency in the behavior of the jsonb - operator when applied to numeric arrays.

 

 

Problem

PostgreSQL allows us to check for the presence of a scalar inside a JSONB array:

 

SELECT jsonb('[2,3,1]') @> to_jsonb(1);

-- Returns true

 

However, when attempting to remove that value from the array using -, the operation fails:

SELECT jsonb('[2,3,1]') - to_jsonb(1);

-- ERROR: operator does not exist: jsonb - jsonb

-- HINT:  You might need to add explicit type casts.


This behavior differs from index-based removal:

SELECT jsonb('[2,3,1]') - 1;

-- Returns [2, 1]


But logically, if @> to_jsonb(1) is true, then jsonb('[2,3,1]') - to_jsonb(1) should remove the value, not the index.

 

Proposal

Support a jsonb - jsonb operator where, if the RHS is a scalar that appears in the LHS array, the operator removes all matching values:

SELECT jsonb('[2,3,1]') - to_jsonb(1);

-- Expected: [2, 3]

This would mirror similar behavior in many application languages and allow value-based deletion from JSON arrays without casting back to SQL arrays or using procedural workarounds.


Impact

The absence of this capability creates a gap in value-level JSONB manipulation. Developers often have to resort to:

  • Procedural code in PL/pgSQL
  • Transforming JSONB arrays into SQL arrays (with limited type support)
  • Writing client-side logic

Adding support for this behavior would simplify many API use cases involving JSON state manipulation.


Happy to clarify further or contribute a patch.

Best regards,
Mark Drake

 

Re: Inconsistent Behavior in JSONB Numeric Array Deletion

От
Robert Haas
Дата:
On Tue, Jun 10, 2025 at 4:52 PM Mark Dake <mark.drake@golden-hind.com> wrote:
> SELECT jsonb('[2,3,1]') @> to_jsonb(1);
> -- Returns true
>
> However, when attempting to remove that value from the array using -, the operation fails:
> SELECT jsonb('[2,3,1]') - to_jsonb(1);
> -- ERROR: operator does not exist: jsonb - jsonb
> -- HINT:  You might need to add explicit type casts.
>
> This behavior differs from index-based removal:
> SELECT jsonb('[2,3,1]') - 1;
> -- Returns [2, 1]
>
> But logically, if @> to_jsonb(1) is true, then jsonb('[2,3,1]') - to_jsonb(1) should remove the value, not the index.

I don't see how you can say that there's anything inconsistent here.
The proposed behavior of the operator you want to add would be
inconsistent with the existing integer subtraction operator, because
the former would remove by value and the latter removes by index. But
there's no inconsistency right now because the operator you want to
add doesn't exist yet. And I don't think the fact that @>(jsonb,jsonb)
exists can reasonably be said to be inconsistent with the fact that
-(jsonb,jsonb) doesn't, either.

Now, none of that means that we couldn't define -(jsonb,jsonb) in the
manner you propose. But that's just a feature idea, not an
inconsistency.

--
Robert Haas
EDB: http://www.enterprisedb.com