Re: Repair plan for inet and cidr types - Mailing list pgsql-hackers

From Peter Eisentraut
Subject Re: Repair plan for inet and cidr types
Date
Msg-id Pine.LNX.4.21.0007070156410.4191-100000@localhost.localdomain
Whole thread Raw
In response to Re: Repair plan for inet and cidr types  (darcy@druid.net (D'Arcy J.M. Cain))
List pgsql-hackers
D'Arcy J.M. Cain writes:

> > Automatic casts should not lose information. How would you feel if floats
> > were automatically rounded when you store them into int fields? I think
> > this is an important principle in any type system.
> 
> If it was defined well I would have no problem with it.

That is certainly not how type systems operate anywhere.

> I guess what I was really getting at was this.
> 
>    host OP cidr
> 
> where inet would cast to host on one side and cidr on the other.  What
> we have now is 
> 
>    cidr OP cidr
> 
> with both sides casting to cidr.  Of course there is no such thing as a host
> type so I don't know how we would cast such a thing.

I think that while the implicit casting could sometimes be convenient,
it's also a source of confusion. Consider the statement

select '10.0.0.3'::cidr < '10.0.0.2'::inet;    => f

This cannot possibly make sense on closer inspection. Firstly, it's
semantic nonsense, you cannot order a network and a host. Secondly, it's
also wrong. According to the documentation, the '10.0.0.3'::cidr should be
converted to '10/8' internally. Then one of two things could have happened
here: 1) cidr was implicitly converted to inet and '10.0.0.3' is taken to
be a host, which is completely wrong. Or 2) inet was converted to cidr.
But then we're looking at '10/8' < '10.0.0.2/32', which should be true.

See also

select '10.0.0.2'::cidr = '10.0.0.2'::inet;    => t

which is wrong for similar reasons.


Then let's look at the << family of operators.

select '10.0.0.2'::cidr >> '10.0.0.2'::inet;    => f

Again, there are two ways this could currently be resolved:
'10/8'::cidr >> '10.0.0.2/32'::cidr    which does return true
or'10.0.0.2'::inet >> '10.0.0.2'::inet
which doesn't make any sense.

On closer inspection, the inet << cidr case is completely misbehaving:

select '10.0.0.5/8'::inet << '10.0.0.0/16'::cidr;    => f
select '10.0.0.5/24'::inet << '10.0.0.0/16'::cidr;    => t

This is not what I'd expect.

Concretely, the casesinet << cidrcidr << cidr
are not the same:
'10.0.0.5/8'::inet << '10.0.0.0/16'::cidr
should be true
'10.0.0.5/8'::cidr << '10.0.0.0/16'::cidr
should be false, if you allow the left-side value in at all, which I
wouldn't.

What this tells me is that the cast from inet to cidr is not well-defined
in the mathematical sense, and therefore no implicit casting should be
allowed.

So the bottom line here is that these two types are, while from a related
domain, different, and the user should be the one that controls when and
how they are mixed together.


-- 
Peter Eisentraut                  Sernanders väg 10:115
peter_e@gmx.net                   75262 Uppsala
http://yi.org/peter-e/            Sweden



pgsql-hackers by date:

Previous
From: Peter Eisentraut
Date:
Subject: SQL float types
Next
From: Peter Eisentraut
Date:
Subject: Re: zlib for pg_dump