Thread: NULL safe equality operator

NULL safe equality operator

From
Christopher Kings-Lynne
Date:
Hi guys,

Does anyone know how I'd go about implementing the following MySQL 
operator in PostgreSQL?

---

NULL-safe equal. This operator performs an equality comparison like the 
=  operator, but returns 1 rather than NULL if both operands are NULL, 
and 0 rather than NULL if one operand isNULL.

mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;        -> 1, 1, 0
mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;        -> 1, NULL, NULL

---

Chris



Re: NULL safe equality operator

From
Michael Glaesemann
Date:
On Nov 25, 2005, at 11:17 , Christopher Kings-Lynne wrote:

> Hi guys,
>
> Does anyone know how I'd go about implementing the following MySQL  
> operator in PostgreSQL?

I'm sure you know how to implement this with a stored procedure.  
AFAICT, if you wanted to actually implement this as an operator,  
you'd need to write C procedures for each datatype to make it an  
operator. Is that something you're looking at doing?

Michael Glaesemann
grzm myrealbox com


create or replace function null_safe_cmp (integer, integer) returns int
immutable language sql as $$
select case    when $1 is null and $2 is null then 1    when ($1 is null and $2 is not null)        or ($1 is not null
and$2 is null) then 0    else case when $1 = $2 then 1 else 0 end
 
end;
$$;

test=# select null_safe_cmp(1,1);
null_safe_cmp
---------------             1
(1 row)

test=# select null_safe_cmp(0,1);
null_safe_cmp
---------------             0
(1 row)

test=# select null_safe_cmp(1,0);
null_safe_cmp
---------------             0
(1 row)

test=# select null_safe_cmp(NULL,1);
null_safe_cmp
---------------             0
(1 row)

test=# select null_safe_cmp(1,NULL);
null_safe_cmp
---------------             0
(1 row)

test=# select null_safe_cmp(NULL,NULL);
null_safe_cmp
---------------             1
(1 row)



Re: NULL safe equality operator

From
Tom Lane
Date:
Christopher Kings-Lynne <chriskl@familyhealth.com.au> writes:
> Does anyone know how I'd go about implementing the following MySQL 
> operator in PostgreSQL?

NOT (x IS DISTINCT FROM y) would be the standard-compliant way of
spelling that.
        regards, tom lane


Re: NULL safe equality operator

From
Dennis Bjorklund
Date:
On Thu, 24 Nov 2005, Tom Lane wrote:

> NOT (x IS DISTINCT FROM y) would be the standard-compliant way of
> spelling that.

That's the sql99 way. In sql2003 (but not in pg) one can also do
 X IS NOT DISTINCT FROM y

-- 
/Dennis Björklund



Re: NULL safe equality operator

From
Christopher Kings-Lynne
Date:
>     when ($1 is null and $2 is not null)
>         or ($1 is not null and $2 is null) then 0

That's the same as:

when $1 is null != $2 is null then 0

Chris



Re: NULL safe equality operator

From
Michael Glaesemann
Date:
On Nov 25, 2005, at 16:24 , Christopher Kings-Lynne wrote:

>>     when ($1 is null and $2 is not null)
>>         or ($1 is not null and $2 is null) then 0
>
> That's the same as:
>
> when $1 is null != $2 is null then 0

Yeah, I saw your commit. Nice shortcut. Also didn't know you could  
define operators using SQL functions. Tom's suggestion of NOT (a  
DISTINCT FROM b) is really cool. Much cleaner in my opinion. I learn  
a lot from these lists :)

Michael Glaesemann
grzm myrealbox com





Re: NULL safe equality operator

From
Christopher Kings-Lynne
Date:
> Yeah, I saw your commit. Nice shortcut. Also didn't know you could  
> define operators using SQL functions. Tom's suggestion of NOT (a  
> DISTINCT FROM b) is really cool. Much cleaner in my opinion. I learn  a 
> lot from these lists :)

Needs to return 0 or 1 though.

Chris



Re: NULL safe equality operator

From
Michael Glaesemann
Date:
On Nov 25, 2005, at 16:37 , Michael Glaesemann wrote:
> Tom's suggestion of NOT (a DISTINCT FROM b) is really cool.

Even cooler if I spell it correctly: NOT (a IS DISTINCT FROM b)

Michael Glaesemann
grzm myrealbox com





Re: NULL safe equality operator

From
Michael Glaesemann
Date:
On Nov 25, 2005, at 16:43 , Christopher Kings-Lynne wrote:

>> Yeah, I saw your commit. Nice shortcut. Also didn't know you  
>> could  define operators using SQL functions. Tom's suggestion of  
>> NOT (a  DISTINCT FROM b) is really cool. Much cleaner in my  
>> opinion. I learn  a lot from these lists :)
>
> Needs to return 0 or 1 though.

CREATE OR REPLACE FUNCTION null_safe_cmp (ANYELEMENT, ANYELEMENT)
RETURNS INTEGER IMMUTABLE
LANGUAGE SQL AS $$
SELECT CASE    WHEN NOT ($1 IS DISTINCT FROM $2) THEN 1    ELSE 0
END;
$$;

select null_safe_cmp (1,1) as "(1,1)"    , null_safe_cmp (1,0) as "(1,0)"    , null_safe_cmp (1,NULL) as "(1,NULL)"
,null_safe_cmp (NULL,1) as "(NULL,1)"    , null_safe_cmp (NULL::integer,NULL::integer) as "(NULL,NULL)";
 
(1,1) | (1,0) | (1,NULL) | (NULL,1) | (NULL,NULL)
-------+-------+----------+----------+-------------     1 |     0 |        0 |        0 |           1
(1 row)

test=# select null_safe_cmp (NULL,NULL);
ERROR:  could not determine anyarray/anyelement type because input  
has type "unknown"
test=# select null_safe_cmp (NULL::integer,NULL::integer);
null_safe_cmp
---------------             1
(1 row)

Same casting problem due to anyelement, of course.

Michael Glaesemann
grzm myrealbox com






Re: NULL safe equality operator

From
Christopher Kings-Lynne
Date:
> test=# select null_safe_cmp (NULL,NULL);
> ERROR:  could not determine anyarray/anyelement type because input  has 
> type "unknown"
> test=# select null_safe_cmp (NULL::integer,NULL::integer);
> null_safe_cmp
> ---------------
>              1
> (1 row)
> 
> Same casting problem due to anyelement, of course.

Yes - I wonder what the trick to getting around that is?

Chris



Re: NULL safe equality operator

From
Christopher Kings-Lynne
Date:
> CREATE OR REPLACE FUNCTION null_safe_cmp (ANYELEMENT, ANYELEMENT)
> RETURNS INTEGER IMMUTABLE
> LANGUAGE SQL AS $$
> SELECT CASE
>     WHEN NOT ($1 IS DISTINCT FROM $2) THEN 1
>     ELSE 0
> END;
> $$;

Even cooler:

CREATE OR REPLACE FUNCTION null_safe_cmp(anyelement, anyelement)
RETURNS integer AS '  SELECT (NOT ($1 IS DISTINCT FROM $2))::integer
' IMMUTABLE LANGUAGE SQL;



Re: NULL safe equality operator

From
Michael Glaesemann
Date:
On Nov 25, 2005, at 17:06 , Christopher Kings-Lynne wrote:

>> test=# select null_safe_cmp (NULL,NULL);
>> ERROR:  could not determine anyarray/anyelement type because  
>> input  has type "unknown"
>> test=# select null_safe_cmp (NULL::integer,NULL::integer);
>> null_safe_cmp
>> ---------------
>>              1
>> (1 row)
>> Same casting problem due to anyelement, of course.
>
> Yes - I wonder what the trick to getting around that is?

Don't use NULL.

Michael Glaesemann
grzm myrealbox com





Re: NULL safe equality operator

From
Peter Eisentraut
Date:
Christopher Kings-Lynne wrote:
> Needs to return 0 or 1 though.

All Boolean operators in MySQL do that, so to create an illusion of 
MySQL compatibility, you'd need to redefine all standard Boolean 
operators.  I don't think you want that.

-- 
Peter Eisentraut
http://developer.postgresql.org/~petere/


Re: NULL safe equality operator

From
"R, Rajesh (STSD)"
Date:
Hello there,

I have included the ipv6 auth. line in my pg_hba.conf file(::1/128)
I keep getting error msgs from postmaster everytime I try to
connect.

Going by previous posts on the topic am unable to conclude.
Does this mean pg 8.0.3 doesn't support ipv6 client auth. ??
Or is there a patch somewhere ??
Plz reply.Thanks in advance.

--
Rajesh R


Re: NULL safe equality operator

From
Tom Lane
Date:
Christopher Kings-Lynne <chriskl@familyhealth.com.au> writes:
>> test=# select null_safe_cmp (NULL,NULL);
>> ERROR:  could not determine anyarray/anyelement type because input  has 
>> type "unknown"
>> Same casting problem due to anyelement, of course.

> Yes - I wonder what the trick to getting around that is?

You might be able to hack it by creating a second function defined asnull_safe_cmp(unknown,unknown)
Pretty grotty of course, and I'm not sure that it comes up in the
real world as opposed to test cases.
        regards, tom lane


Re: NULL safe equality operator

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Christopher Kings-Lynne wrote:
>> Needs to return 0 or 1 though.

> All Boolean operators in MySQL do that, so to create an illusion of 
> MySQL compatibility, you'd need to redefine all standard Boolean 
> operators.  I don't think you want that.

Wonder if making an implicit cast from bool to int would answer for
that.
        regards, tom lane