-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Problem
I've defined the following domain representation for a non-nullable TIMESTAMPTZ column that reports -infinity as null in the JSON representation and when filtering.
CREATE DOMAIN common."TimeValidFromType" AS TIMESTAMPTZ;
CREATE FUNCTION common."TimeValidFromTypeToJson"(ts common."TimeValidFromType")
RETURNS JSON
AS $$
SELECT to_json(CASE WHEN NOT isfinite(ts)
THEN NULL
ELSE ts
END)
$$
LANGUAGE SQL IMMUTABLE;
CREATE CAST (common."TimeValidFromType" AS JSON) WITH FUNCTION common."TimeValidFromTypeToJson"(common."TimeValidFromType") AS IMPLICIT;
CREATE FUNCTION common."JsonToTimeValidFromType"(js JSON)
RETURNS common."TimeValidFromType"
AS $$
SELECT (CASE WHEN js IS NULL
THEN '-infinity'
ELSE js::TEXT
END)::common."TimeValidFromType"
$$
LANGUAGE SQL IMMUTABLE;
CREATE CAST (JSON AS common."TimeValidFromType") WITH FUNCTION common."JsonToTimeValidFromType"(JSON) AS IMPLICIT;
CREATE FUNCTION common."TextToTimeValidFromType"(tx TEXT)
RETURNS common."TimeValidFromType"
AS $$
-- Convert an empty string as well since that's what the Supabase.Postgrest client
-- sends when it creates a primary key filter from a null value.
-- Convert the string 'null' as well since "is.null" will not work as a PostgREST
-- filter and so we have to use "eq.null" instead.
SELECT (CASE WHEN tx IS NULL OR tx = '' OR tx = 'null'
THEN '-infinity'
ELSE tx
END)::common."TimeValidFromType"
$$
LANGUAGE SQL IMMUTABLE;
CREATE CAST (TEXT AS common."TimeValidFromType") WITH FUNCTION common."TextToTimeValidFromType"(TEXT) AS IMPLICIT;The issue is that clients are not able to use the is.null/not.is.null filters on this column because internally the column is never null. But the domain representation reports the field as null, and so for API consistency it would be great if is.null/not.is.null worked as expected from the client's perspective.
The workaround that I've implemented above is to convert the "null" string in filter requests so that eq.null/not.eq.null works for this field. That's obviously not ideal since it means a different syntax for this one column.
Solution
Whenever is.null/not.is.null is applied to a field that contains a TEXT domain representation conversion function, pass null into the function and use the return value of the function in the SQL IS check.
Versions
PostgreSQL: 18.0
PostgREST: v14.0