@@ -50,6 +50,16 @@ export function cellValueFilterConditions(
5050 return supports ( 'isEmpty' ) ? [ { field, op : 'isEmpty' } ] : [ ]
5151 }
5252
53+ // A `json` column has no same-value filter to offer, whatever the cell holds.
54+ // It must be checked BEFORE the shape branches below: `json.coerce` accepts
55+ // anything, so a json cell holds arrays and scalars alike, and letting a
56+ // string array through the multi-select branch would emit `contains` — which
57+ // the server accepts on json and compiles to ILIKE substring matching, so
58+ // unrelated rows would match. `eq` there is refused outright by `validateLeaf`
59+ // in `query-builder/validate.ts`, and a refused predicate would stay in state
60+ // and 400 every later refetch. Only the emptiness check above survives.
61+ if ( column . type === 'json' ) return [ ]
62+
5363 // A multi-select cell holds several option ids, so "the same as this cell"
5464 // is one membership test per id — equality against the whole array can never
5565 // be true. Every id must be filterable, or the row the user clicked would
@@ -60,13 +70,8 @@ export function cellValueFilterConditions(
6070 return value . map ( ( id ) => ( { field, op : 'contains' , value : id } ) satisfies Predicate )
6171 }
6272
63- // No equality to offer: `validateLeaf` in `query-builder/validate.ts` rejects
64- // the containment operators on a `json` column outright, and a rejected
65- // predicate would stay in state and 400 every later refetch. `json.coerce`
66- // accepts anything, so its cells hold scalars too — the type, not the value
67- // shape, is what decides. The `typeof` guard covers a structured value
68- // reaching any other type.
69- if ( column . type === 'json' || typeof value === 'object' ) return [ ]
73+ // A structured value on any other column type has no meaningful equality.
74+ if ( typeof value === 'object' ) return [ ]
7075 if ( ! supports ( 'eq' ) ) return [ ]
7176 return [ { field, op : 'eq' , value : value as JsonValue } ]
7277}
0 commit comments