feat: Adds new filters to increase Postgrest parity#81
Conversation
Adds like, ilike, is, match, imatch, and isdistinct filter operators to realtime subscriptions, along with a negate flag on user_defined_filter to support NOT variants (e.g. IS NOT, IS NOT DISTINCT FROM). This increases our parity with Postgrest filters
| language sql | ||
| immutable | ||
| as $$ | ||
| select |
There was a problem hiding this comment.
Can we restore the previous NULL handling here? The old implementation treated a NULL comparison result as a failed filter via bool_and(coalesce(check_equality_op(...), false)). This
version can turn unknown comparisons into visible rows because the outer coalesce(..., true) defaults to allow. For example, page_id = 5 should not match a row where page_id is
NULL.
| true | ||
| ) | ||
| from | ||
| unnest(filters) f |
There was a problem hiding this comment.
This should probably "fail closed" when a filtered column is missing from the WAL payload. With the inner join, a filter whose column is absent can produce zero evaluated rows, and the
function can default to visible. For DELETEs without replica identity full, this means a filter on a non-PK column may pass even though we cannot evaluate it. Could we left join filters
to columns and require every filter to have a matching column, e.g. count(col.name) = count(f.column_name)?
|
|
||
| alter type realtime.user_defined_filter add attribute negate boolean; | ||
|
|
||
| create or replace function realtime.check_equality_op( |
There was a problem hiding this comment.
This creates a 5-arg overload with negate DEFAULT false, but the existing 4-arg check_equality_op remains. That makes old calls like check_equality_op('eq', 'text', 'aaa', 'aaa')
ambiguous. If the default is intended to preserve compatibility, can we drop the old 4-arg function in this migration after dependents are updated, or otherwise avoid the overload
ambiguity?
| } | | | | ||
| (1 row) | ||
|
|
||
| -- Expect 0 subscriptions: filters do match 5 <> null |
There was a problem hiding this comment.
This expected output looks like it accepts a regression. The test comment says the NULL row should match 0 subscriptions for page_id = 5, but the expected output includes the
subscription id. Can we keep this expectation as {} and fix the filter logic instead?
| "name": "page_id", +| | | | ||
| "type": "int4" +| | | | ||
| } +| | | | ||
| ], +| | | |
There was a problem hiding this comment.
This expected output also looks too permissive. In the non-full replica identity case, the WAL payload only has the PK, so the body = 'bbb' filter cannot be evaluated and should not
match. Can we keep the previous expectation where only the PK-based filter matches?
6e8535b to
3cbb2cb
Compare
3cbb2cb to
6f02022
Compare
What kind of change does this PR introduce?
Adds like, ilike, is, match, imatch, and isdistinct filter operators to realtime subscriptions, along with a negate flag on user_defined_filter to support NOT variants (e.g. IS NOT, IS NOT DISTINCT FROM).
This increases our parity with Postgrest filters
https://linear.app/supabase/issue/REAL-832/improve-filter-parity-based-on-postgrest