I'm currently implementing a translation between a proprietary expression language and postgres queries at work. So far a lot of stuff fell in place quite nicely, but now I have trouble with one function.
The source language contains a function (contains
) that checks whether the first argument contains the second. That means for
- strings: It checks whether the second arg is a substring of the first arg.
- arrays: The second arg is an element of the array (first arg)
- objects/maps/dicts: The second argument is a key of the object (first arg)
Now comes the issue: The translation doesn't know anything about the DB schema, so the queries need to be generic enough to work on different kinds of schemas. So I don't know whether a given field is of a specific type. It is okay to fail in some cases, but I would at least like the code to work for the types text/varchar , text[] and jsonb. But I'm struggling to get even the first two to work. Here is the (incomplete) WHERE clause of a query that is generated by the translator:
CASE
WHEN pg_typeof(entity.field1)::text = ANY('{text,character varying}') THEN ( entity.field1 LIKE '%' || entity.field2|| '%' )
WHEN pg_typeof(entity.field1)::text = 'text[]' THEN ( entity.field2=ANY(entity.field1))
[...]
ELSE false
END
Let's assume (for now) that entity.field2 is a text column. entity.field1 is
- a) a text column
- b) a text[] column
The query works fine for a), as expected. But it fails for b) with:
operator does not exist: text[] ~~ text
So I broke the query down to:
CASE
WHEN false THEN ( entity.field1 LIKE '%' || entity.field2 || '%' )
ELSE false
END
For a) false is returned, as expected. For b) the error is still thrown. So it seems like the operator type check is run, even if there is no way to reach the code in the THEN
clause.
I tried to find the reason for that in the docs but I didn't. This paragraph contains some info on early evaluation, but not related to operator type checks.
So, is there a way to get this to work by catching errors, casting (have tried naively casting to text, that works for text[]
but not for jsonb
), or anything else?
Thanks in advance for your help, it is greatly appreciated.
WHERE
clause.entity.field1
?