Is there a way to do a non-zero bit string test without hard-coding the bit string width of 0?
For example, suppose I have two tables, Users and Features, each with masks, I want to test this:
SELECT u.name FROM Users u, Features f
WHERE u.mask & f.mask;
matching implicit non-zero results. However, SQL requires an explicit boolean result for WHERE as opposed to an implicit cast, such as this:
SELECT u.name FROM Users u, Features f
WHERE (u.mask & f.mask) != 0::BIT(2048);
I don't want to hardcode 2048 (or whatever) in this query for a number of reasons.
Testing expr = 0 or expr > 0 results in a type error. Oddly, I can test expr = 0::BIT(1), but that gives the wrong answer because Postgres does not consider all all-zero bit strings to be equal.
select 0::BIT(2) > 0::BIT(1);
?column?
----------
t
(1 row)
I can create a calculated zero by doing this:
SELECT u.name FROM Users u, Features f
WHERE (u.mask & f.mask) != (u.mask & ~u.mask);
Which works but feels like an awful hack.
Any suggestions or insights?
RESULTS
I benchmarked several options provided below. Thanks for the suggestions, Erwin!
Based on a very large data set and 100,000 queries, I found the following constructs resulted in the associated queries per second. Hopefully someone from the Postgres team sees this and provides a generic 0 to speed things up! Unfortunately most generic approaches seem to incur a string conversion which is quite expensive.
Constructs | Queries / s
----------------------------------------+--------------
(u.mask & f.mask) <> 0::BIT(2048) | 158
(u.mask & f.mask) <> (u.mask # u.mask) | 135
(u.mask & f.mask) <> (u.mask & ~u.mask) | 125
position('1' IN (u.mask & f.mask)) > 0 | 37
(u.mask & f.mask)::TEXT !~ '^0+$' | 27
non-zero bit string test? And what exactly do you mean bymatching implicit non-zero resultsCan you explain or add some examples what you want to pass and what to fail? Are your columns definedNOT NULL? Please add your table definition (\d usersin psql). What is your Postgres version?