New version of int4hashset_contains() that should follow the same General Rules as MULTISET's MEMBER OF (8.16 <member predicate>).
The first rule is to return False if the cardinality is 0 (zero). However, we must first check if the first argument is null, in which case the cardinality cannot be 0 (zero), so if the first argument is null then we return Unknown (represented as null). We then proceed and check if the set is empty, which is defined as nelements being 0 (zero) as well as the new null_element field being false. If the set is empty, then we always return False, regardless of the second argument, that is, even if it would be null we would still return False, since the set is empty and can therefore not contain any element. The second rule is to return Unknown (represented as null) if any of the arguments are null. We've already checked that the first argument is not null, so now we check the second argument, and return Unknown (represented as null) if it is null. The third rule is to check for the element, and return True if the set contains the element. Otherwise, if the set contains the null element, we don't know if the element we're checking for is in the set, so we then return Unknown (represented as null). Finally, if the set doesn't contain the null element and nor the element we're checking for, then we return False. Datum int4hashset_contains(PG_FUNCTION_ARGS) { int4hashset_t *set; int32 value; bool result; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); set = PG_GETARG_INT4HASHSET(0); if (set->nelements == 0 && !set->null_element) PG_RETURN_BOOL(false); if (PG_ARGISNULL(1)) PG_RETURN_NULL(); value = PG_GETARG_INT32(1); result = int4hashset_contains_element(set, value); if (!result && set->null_element) PG_RETURN_NULL(); PG_RETURN_BOOL(result); } Example queries and expected results: SELECT hashset_contains(NULL::int4hashset, NULL::int); -- null SELECT hashset_contains(NULL::int4hashset, 1::int); -- null SELECT hashset_contains('{}'::int4hashset, NULL::int); -- false SELECT hashset_contains('{}'::int4hashset, 1::int); -- false SELECT hashset_contains('{null}'::int4hashset, NULL::int); -- null SELECT hashset_contains('{null}'::int4hashset, 1::int); -- null SELECT hashset_contains('{1}'::int4hashset, NULL::int); -- null SELECT hashset_contains('{1}'::int4hashset, 1::int); -- true SELECT hashset_contains('{1}'::int4hashset, 2::int); -- false Looks good? /Joel