Thread: Summary: what to do about INET/CIDR

Summary: what to do about INET/CIDR

From
Tom Lane
Date:
After reviewing a number of past threads about the INET/CIDR mess,
I have concluded that we should adopt the following behavior:

1.  A data value like '10.1.2.3/16' is a legal INET value (it implies
the host 10.1.2.3 in the network 10.1/16) but not a legal CIDR value.
Hence, cidr_in should reject such a value.  Up to now it hasn't.

2.  We do not have a datatype corresponding strictly to a host address
alone --- to store a plain address, use INET and let the mask width
default to 32.  inet_out suppresses display of a "/32" netmask (whereas
cidr_out does not).

3.  Given that CIDRs never have invalid bits set, we can use the same
ordering rules for both datatypes: sort by address part, then by
number of bits.  This is compatible with what 7.0 did when sorting.
It is *not* quite the same as what current sources do, but I will revert
that change.

I didn't see anyone objecting to this scheme in past discussions, but
I also didn't see any clear statement that all the interested parties
had agreed to it.  Last chance to complain...
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
The Hermit Hacker
Date:
makes sense to me

On Thu, 26 Oct 2000, Tom Lane wrote:

> After reviewing a number of past threads about the INET/CIDR mess,
> I have concluded that we should adopt the following behavior:
> 
> 1.  A data value like '10.1.2.3/16' is a legal INET value (it implies
> the host 10.1.2.3 in the network 10.1/16) but not a legal CIDR value.
> Hence, cidr_in should reject such a value.  Up to now it hasn't.
> 
> 2.  We do not have a datatype corresponding strictly to a host address
> alone --- to store a plain address, use INET and let the mask width
> default to 32.  inet_out suppresses display of a "/32" netmask (whereas
> cidr_out does not).
> 
> 3.  Given that CIDRs never have invalid bits set, we can use the same
> ordering rules for both datatypes: sort by address part, then by
> number of bits.  This is compatible with what 7.0 did when sorting.
> It is *not* quite the same as what current sources do, but I will revert
> that change.
> 
> I didn't see anyone objecting to this scheme in past discussions, but
> I also didn't see any clear statement that all the interested parties
> had agreed to it.  Last chance to complain...
> 
>             regards, tom lane
> 
> 

Marc G. Fournier                   ICQ#7615664               IRC Nick: Scrappy
Systems Administrator @ hub.org 
primary: scrappy@hub.org           secondary: scrappy@{freebsd|postgresql}.org 



Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001026 18:46]:
> After reviewing a number of past threads about the INET/CIDR mess,
> I have concluded that we should adopt the following behavior:
> 
> 1.  A data value like '10.1.2.3/16' is a legal INET value (it implies
> the host 10.1.2.3 in the network 10.1/16) but not a legal CIDR value.
> Hence, cidr_in should reject such a value.  Up to now it hasn't.
> 
> 2.  We do not have a datatype corresponding strictly to a host address
> alone --- to store a plain address, use INET and let the mask width
> default to 32.  inet_out suppresses display of a "/32" netmask (whereas
> cidr_out does not).
> 
> 3.  Given that CIDRs never have invalid bits set, we can use the same
> ordering rules for both datatypes: sort by address part, then by
> number of bits.  This is compatible with what 7.0 did when sorting.
> It is *not* quite the same as what current sources do, but I will revert
> that change.
> 
> I didn't see anyone objecting to this scheme in past discussions, but
> I also didn't see any clear statement that all the interested parties
> had agreed to it.  Last chance to complain...
I'd like to see a way to get all 4 octets of a CIDR printed out... 

Also a way to get network (.0) and broadcast (all ones) for a cidr
block out of our stuff. 

Larry
> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Larry Rosenman <ler@lerctr.org> writes:
> Also a way to get network (.0) and broadcast (all ones) for a cidr
> block out of our stuff. 

network() and broadcast() have been there all along ...
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 09:49]:
> Larry Rosenman <ler@lerctr.org> writes:
> > Also a way to get network (.0) and broadcast (all ones) for a cidr
> > block out of our stuff. 
> 
> network() and broadcast() have been there all along ...
but don't work on CIDR types.....

LER

> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Larry Rosenman <ler@lerctr.org> [001027 09:51]:
> * Tom Lane <tgl@sss.pgh.pa.us> [001027 09:49]:
> > Larry Rosenman <ler@lerctr.org> writes:
> > > Also a way to get network (.0) and broadcast (all ones) for a cidr
> > > block out of our stuff. 
> > 
> > network() and broadcast() have been there all along ...
> but don't work on CIDR types.....
And I get to be wrong.  

Sorry about that. 

But, it would still be nice if we can force all 4 octets to be printed
for the network funcs..

LER

> 
> LER
> 
> > 
> >             regards, tom lane
> -- 
> Larry Rosenman                      http://www.lerctr.org/~ler
> Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
> US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Larry Rosenman <ler@lerctr.org> [001027 11:08]:
> * Tom Lane <tgl@sss.pgh.pa.us> [001027 09:49]:
> > Larry Rosenman <ler@lerctr.org> writes:
> > > Also a way to get network (.0) and broadcast (all ones) for a cidr
> > > block out of our stuff. 
> > 
> > network() and broadcast() have been there all along ...
> OK, what I really meant was a way to coerce a CIDR entity to INET so 
> that host() can work with a CIDR type to print all 4 octets. 
> 
> Does this help with what I want?  
> 
> Currently you can't coerce a CIDR type to INET. 
For example, I feel the following should work:

ler=# \d ler_test     Table "ler_test"Attribute | Type | Modifier
-----------+------+----------net       | cidr |host      | inet |

ler=# select * from ler_test;     net      |       host
---------------+------------------207.158.72/24 | 207.158.72.11/24
(1 row)

ler=# select host(net::inet) from ler_test;
ERROR:  CIDR type has no host part
ERROR:  CIDR type has no host part
ler=#
> 
> > 
> >             regards, tom lane
> -- 
> Larry Rosenman                      http://www.lerctr.org/~ler
> Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
> US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 09:49]:
> Larry Rosenman <ler@lerctr.org> writes:
> > Also a way to get network (.0) and broadcast (all ones) for a cidr
> > block out of our stuff. 
> 
> network() and broadcast() have been there all along ...
OK, what I really meant was a way to coerce a CIDR entity to INET so 
that host() can work with a CIDR type to print all 4 octets. 

Does this help with what I want?  

Currently you can't coerce a CIDR type to INET. 

> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Inet is supposed to be host address, with optional network specification.

Agreed.  As such, it probably should always display all 4 octets
regardless of the maskwidth.  It doesn't do that at the moment:

regression=# select '127.0.0.1/8'::inet;?column?
----------127.0/8
(1 row)

This is clearly bad.  I will change it to produce '127.0.0.1/8',
unless someone has a better idea.

> I also have in my notes (some might have been fixed since):

> * inet output is broken => 127.0.0.1/8

See above.

> * no cast function to "text" available

I don't see much point in solving that issue on a one-datatype-at-a-time
basis.  Sooner or later we should fix things so that the datatype I/O
conversion functions can be invoked safely in expressions.

> * equality/distinctness is broken in certain cases => select
> '10.0.0.1/27'::inet='10.0.0.2/27'::inet; returns true

This is now fixed.

> * operator commutators and negators are incorrect

Fixed.

> * ouput functions apparently null-terminate their result => select
> host('10.0.0.1')='10.0.0.1'; returns false

Not sure what that has to do with output functions, but I get 'true'
now.

> * comparing inet and cidr is not well defined

Perhaps not.  There was a whole lot of argument about that point,
and it didn't seem to me that we came to any real agreement.

> * should '127.0.0.1/24'::cidr fail?

Looks like we've resolved that as "yes".

There are still unresolved issues about whether inet and cidr should be
considered binary-equivalent, what network_sup/sub mean when comparing
inet and cidr, whether we are missing any important functions, etc.
I'm not hoping to get these resolved for 7.1, considering we are nearly
at beta stage and don't even have a complete proposal for what to do.
I'm satisfied for the moment with having eliminated the failure to
compare all bits of the values, which led to bogus equality results
and consequent malfunction of indexes.
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Peter Eisentraut
Date:
Tom Lane writes:

> 1.  A data value like '10.1.2.3/16' is a legal INET value (it implies
> the host 10.1.2.3 in the network 10.1/16) but not a legal CIDR value.
> Hence, cidr_in should reject such a value.  Up to now it hasn't.

Nod.

> 2.  We do not have a datatype corresponding strictly to a host address
> alone --- to store a plain address, use INET and let the mask width
> default to 32.  inet_out suppresses display of a "/32" netmask (whereas
> cidr_out does not).

Inet is supposed to be host address, with optional network specification.

I also have in my notes (some might have been fixed since):

* inet output is broken => 127.0.0.1/8
* no cast function to "text" available (what about host()?)
* equality/distinctness is broken in certain cases => select
'10.0.0.1/27'::inet='10.0.0.2/27'::inet; returns true
* operator commutators and negators are incorrect
* ouput functions apparently null-terminate their result => select
host('10.0.0.1')='10.0.0.1'; returns false
* comparing inet and cidr is not well defined
* should '127.0.0.1/24'::cidr fail?

-- 
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/



Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Larry Rosenman wrote:
> ler=# select * from ler_test;
>       net      |       host
> ---------------+------------------
>  207.158.72/24 | 207.158.72.11/24
> (1 row)
> 
> ler=# select host(net::inet) from ler_test;
> ERROR:  CIDR type has no host part
> ERROR:  CIDR type has no host part
I agree. There should be a coercion function, but it should never be
automatic...But since now there aren't any automatic coercions, that's not
a problem ;)

Also, I agree with Larry that cidr _must_ be printed with 4 octets in
them, whether they are 0 or not. (i.e. it should print 207.158.72.0/24)

This is the standard way of specifying addresses in all network equipment.
RFC specifies that, just the library that we use doesn't (yes, it is from
Vixie, but it doesn't make it RFC-compliant)

I'll submit patches in a week or so, when I start straightening out my
network equipment tables...;)

-alex



Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Alex Pilosov <alex@pilosoft.com> [001027 14:43]:
> On Fri, 27 Oct 2000, Larry Rosenman wrote:
> > ler=# select * from ler_test;
> >       net      |       host
> > ---------------+------------------
> >  207.158.72/24 | 207.158.72.11/24
> > (1 row)
> > 
> > ler=# select host(net::inet) from ler_test;
> > ERROR:  CIDR type has no host part
> > ERROR:  CIDR type has no host part
> I agree. There should be a coercion function, but it should never be
> automatic...But since now there aren't any automatic coercions, that's not
> a problem ;)
> 
> Also, I agree with Larry that cidr _must_ be printed with 4 octets in
> them, whether they are 0 or not. (i.e. it should print 207.158.72.0/24)
> 
> This is the standard way of specifying addresses in all network equipment.
> RFC specifies that, just the library that we use doesn't (yes, it is from
> Vixie, but it doesn't make it RFC-compliant)
and network(cidr) should print ONLY the octets, not the mask...

LER

> 
> I'll submit patches in a week or so, when I start straightening out my
> network equipment tables...;)
> 
> -alex

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Larry Rosenman wrote:
> and network(cidr) should print ONLY the octets, not the mask...
Agreed. There's a function to get the mask size, and the network should
just return the network. Otherwise, it is impossible to use.

-alex



Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Larry Rosenman <ler@lerctr.org> writes:
> OK, what I really meant was a way to coerce a CIDR entity to INET so 
> that host() can work with a CIDR type to print all 4 octets. 

Hm.  I don't see any really good reason why host() rejects CIDR input
in the first place.  What's wrong with producing the host address
that corresponds to extending the CIDR network address with zeroes?

> Currently you can't coerce a CIDR type to INET. 

Well you can, but it doesn't *do* anything.  One of the peculiarities
of these two types is that the cidr-vs-inet flag is actually stored
in the data value.  The type-system differentiation between CIDR and
INET is a complete no-op for everything except initial entry of a value
(ie, conversion of a text string to CIDR or INET); all the operators
that care (which is darn few ... in fact it looks like host() is the
only one!) look right at the value to see which type they've been given.
So applying a type coercion may make the type system happy, but it
doesn't do a darn thing to the bits, and thus not to the behavior of
subsequent operators either.  I have not yet figured out if that's a
good thing or a bad thing ...
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Alex Pilosov <alex@pilosoft.com> writes:
> Also, I agree with Larry that cidr _must_ be printed with 4 octets in
> them, whether they are 0 or not. (i.e. it should print 207.158.72.0/24)

> This is the standard way of specifying addresses in all network equipment.
> RFC specifies that, just the library that we use doesn't (yes, it is from
> Vixie, but it doesn't make it RFC-compliant)

Somehow, I am more inclined to believe Vixie's opinion on this than
either yours or Larry's ;-)

If you think there is an RFC that demands the above behavior and not
what Vixie recommended to us, let's see chapter and verse.

FWIW, the direction we seem to be converging in is that INET will always
print all four octets.  Maybe the answer for you is to use INET, rather
than to try to persuade us that you understand CIDR notation better than
Vixie does...
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 15:14]:
> Alex Pilosov <alex@pilosoft.com> writes:
> > Also, I agree with Larry that cidr _must_ be printed with 4 octets in
> > them, whether they are 0 or not. (i.e. it should print 207.158.72.0/24)
> 
> > This is the standard way of specifying addresses in all network equipment.
> > RFC specifies that, just the library that we use doesn't (yes, it is from
> > Vixie, but it doesn't make it RFC-compliant)
> 
> Somehow, I am more inclined to believe Vixie's opinion on this than
> either yours or Larry's ;-)
> 
> If you think there is an RFC that demands the above behavior and not
> what Vixie recommended to us, let's see chapter and verse.
> 
> FWIW, the direction we seem to be converging in is that INET will always
> print all four octets.  Maybe the answer for you is to use INET, rather
> than to try to persuade us that you understand CIDR notation better than
> Vixie does...
What I need is a way to convince PG to print all 4 octets from a CIDR
type.  I *WANT* the safety of the CIDR type for blocks of addresses,
but need to be able to print all 4 octets out for NON-TECHIES. 

LER
> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Tom Lane wrote:

> Larry Rosenman <ler@lerctr.org> writes:
> > OK, what I really meant was a way to coerce a CIDR entity to INET so 
> > that host() can work with a CIDR type to print all 4 octets. 
> 
> Hm.  I don't see any really good reason why host() rejects CIDR input
> in the first place.  What's wrong with producing the host address
> that corresponds to extending the CIDR network address with zeroes?
_maybe_ cuz this is an invalid address. (an address cannot have all-zeros
or all-ones host part). On other hand, postgres doesn't enforce that in
inet_in, so its inconsistent to enforce it there...

> > Currently you can't coerce a CIDR type to INET. 
> 
> Well you can, but it doesn't *do* anything.  One of the peculiarities
> of these two types is that the cidr-vs-inet flag is actually stored
> in the data value.  The type-system differentiation between CIDR and
> INET is a complete no-op for everything except initial entry of a value
> (ie, conversion of a text string to CIDR or INET); all the operators
> that care (which is darn few ... in fact it looks like host() is the
> only one!) look right at the value to see which type they've been given.
> So applying a type coercion may make the type system happy, but it
> doesn't do a darn thing to the bits, and thus not to the behavior of
> subsequent operators either.  I have not yet figured out if that's a
> good thing or a bad thing ...
Probably cidr_inet should make a copy instead of just "blessing" the
original value?

-alex



Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
BTW, does it strike anyone else as peculiar that the host(),
broadcast(), network(), and netmask() functions yield results
of type text, rather than type inet?  Seems like it'd be considerably
more useful if they returned values of type inet with masklen = 32
(except for network(), which would keep the original masklen while
coercing bits to its right to 0).

Given the current proposal that inet_out should always display all 4
octets, and the existing fact that inet_out suppresses display of
a /32 netmask, the textual display of SELECT host(...) etc would
remain the same as it is now.  But AFAICS you could do more with
an inet-type result value, like say compare it to other inet or cidr
values ...

Comments?  Why was it done this way, anyway?
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 17:29]:
> Larry Rosenman <ler@lerctr.org> writes:
> > I.E. for select network('207.158.72.0/24')
> > I get 
> > 207.158.72.0
> 
> To my mind that should be done with host(), not network().  If you strip
> the masklen information then what you have is no longer a network
> specification, so expecting a function named network() to behave that
> way strikes me as bizarre.
Fine, but host() rejects CIDR types right now....

LER
> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 17:04]:
> BTW, does it strike anyone else as peculiar that the host(),
> broadcast(), network(), and netmask() functions yield results
> of type text, rather than type inet?  Seems like it'd be considerably
> more useful if they returned values of type inet with masklen = 32
> (except for network(), which would keep the original masklen while
> coercing bits to its right to 0).
> 
> Given the current proposal that inet_out should always display all 4
> octets, and the existing fact that inet_out suppresses display of
> a /32 netmask, the textual display of SELECT host(...) etc would
> remain the same as it is now.  But AFAICS you could do more with
> an inet-type result value, like say compare it to other inet or cidr
> values ...
> 
> Comments?  Why was it done this way, anyway?
It doesn't bother me, as long as there is someway for me to get from a
CIDR type to 4 octets output with no mask indicated, and print the
broadcast and netmask and bits out separately from ONE column in the
table. 

I.E. for select
network('207.158.72.0/24'),broadcast('207.158.72.0/24'),netmask('207.158.72.0/24') 
I get 

207.158.72.0  207.158.72.255 255.255.255.0 

as output. 

Aside from that, I'm not picky. 

Larry
> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 17:41]:
> Larry Rosenman <ler@lerctr.org> writes:
> > Fine, but host() rejects CIDR types right now....
> 
> What's your point?  network() doesn't behave the way you want right now,
> either.
Fine, network() can return CIDR (207.158.72/24), but allow host(cidr)
to print all 4 octets without the mask. 

Larry
> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Tom Lane wrote:

> The way I'm visualizing this, INET is a generalized type that will store
> any 4-octet address plus any netmask width from 1 to 32.  This includes
> not only host addresses, but network specs and broadcast addresses.
> CIDR is a subset type that only accepts valid network specs (ie, no
> nonzero address bits to the right of the netmask).  There is no subset

I really don't think it should. We should have as much error-checking as
possible. Broadcast address does _not_ have a netmask, i.e. 10.0.0.255/24
does not make sense as inet, it should be 10.0.0.255/32

(ie. broadcast() function must return a value with /32 mask)

> type that corresponds to "valid host addresses only" --- if there were,
> it would be a subset of INET but would have no valid values in common
> with CIDR.  We could make such a type but I dunno if it's worth the
> trouble.



Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Larry Rosenman <ler@lerctr.org> writes:
> I.E. for select network('207.158.72.0/24')
> I get 
> 207.158.72.0

To my mind that should be done with host(), not network().  If you strip
the masklen information then what you have is no longer a network
specification, so expecting a function named network() to behave that
way strikes me as bizarre.
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Alex Pilosov <alex@pilosoft.com> writes:
> On Fri, 27 Oct 2000, Tom Lane wrote:
>> BTW, does it strike anyone else as peculiar that the host(),
>> broadcast(), network(), and netmask() functions yield results
>> of type text, rather than type inet?

> I absolutely agree, except for network(), which should return cidr.

We could do that, but if we did, it would print out per CIDR format
(eg, '192.1/16') whereas both you and Larry have been saying you want
a way to produce '192.1.0.0/16'.  Perhaps we need two functions, one
to produce the network in CIDR notation and one to produce it in INET
notation.

For that matter, perhaps we should not change host() to accept CIDR
but instead provide a separate function that does what I proposed
host() should do with a CIDR.  Not sure.

> As I mentioned in another email, should inet datatype really care whether
> host part is all-ones or all-zeros and reject that?

I'm inclined to think not, partially because that would mean that the
results of broadcast() and network() could *NOT* be considered valid
INET values.

The way I'm visualizing this, INET is a generalized type that will store
any 4-octet address plus any netmask width from 1 to 32.  This includes
not only host addresses, but network specs and broadcast addresses.
CIDR is a subset type that only accepts valid network specs (ie, no
nonzero address bits to the right of the netmask).  There is no subset
type that corresponds to "valid host addresses only" --- if there were,
it would be a subset of INET but would have no valid values in common
with CIDR.  We could make such a type but I dunno if it's worth the
trouble.
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Tom Lane wrote:

> Alex Pilosov <alex@pilosoft.com> writes:
> > Also, I agree with Larry that cidr _must_ be printed with 4 octets in
> > them, whether they are 0 or not. (i.e. it should print 207.158.72.0/24)
> 
> > This is the standard way of specifying addresses in all network equipment.
> > RFC specifies that, just the library that we use doesn't (yes, it is from
> > Vixie, but it doesn't make it RFC-compliant)
> 
> Somehow, I am more inclined to believe Vixie's opinion on this than
> either yours or Larry's ;-)

> If you think there is an RFC that demands the above behavior and not
> what Vixie recommended to us, let's see chapter and verse.

After a long search of RFCs, I could not find any that _mandates_ one way
over the other in all situations. However, in all RFC, whenever an example
of IP addressing is used, the full (10.0.0.0/8) address is used far more
often than compacted (10/8).

I'd give you an example of BIND9, but in its inet_ntop function, it no
longer has the netmask length ;)

All networking software supports full syntax of address. Most of
networking software supports compacted syntax.

Many RFCs relating to the networking software, DO specify that full
version is required:
ftp://ftp.merit.edu/internet/documents/rfc/rfc2622.txt 
ftp://ftp.merit.edu/internet/documents/rfc/rfc2673.txt verse 3.2.1

RIPE NCC (the european version of ARIN) also likes the complete version in
their standards documents (refer:
http://www.lir.garr.it/docs/ripe-121.txt across the document

ARIN in their allocation templates, also uses full version: 
(again, across the document)
http://www.arin.net/regserv/templates/isptemplate.txt
http://www.arin.net/routingreg/route.html
http://www.arin.net/routingreg/route-set.html


If this doesn't persuade you, I think I'll just ask Vixie to settle this.
:)

-alex

> FWIW, the direction we seem to be converging in is that INET will always
> print all four octets.  Maybe the answer for you is to use INET, rather
> than to try to persuade us that you understand CIDR notation better than
> Vixie does...





Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Alex Pilosov <alex@pilosoft.com> writes:
> We should have as much error-checking as possible.

Only possible with a much tighter definition of what the intended use
of each type is.  For example, you seem to be saying that broadcast
addresses aren't valid inet values, with which I do not agree unless
there is another type that they can be part of.

My inclination is to leave INET with the range of valid values it
currently has, and to let people apply column constraints if they
want to restrict a particular column to, say, valid host addresses,
or valid broadcast addresses, or whatever.

> Broadcast address does _not_ have a netmask, i.e. 10.0.0.255/24
> does not make sense as inet, it should be 10.0.0.255/32

How so?  Without a netmask you have no way to know if it's a broadcast
address or not. 10.0.0.255/32 might be a perfectly valid host address
in, say, 10.0/16.  But 10.0.0.255/24 is recognizably the broadcast
address for 10.0.0/24 (and not for any other network...)

> (ie. broadcast() function must return a value with /32 mask)

I don't disagree with that part, but that's only because I see
broadcast() as mainly a display convenience.  If we had a larger and
more thoroughly worked out set of inet/cidr operators, I'd be inclined
to argue that broadcast('10.0.0.0/24') should yield 10.0.0.255/24 for
computational convenience.  Then we'd need to offer a separate function
that would let you strip off the netmask for display purposes (actually
host() would do for that...)
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 21:53]:
> >>>> e) have a function network(inet) which would look up the address in a
> >>>> table of networks using longest-prefix-match. I.E. something similar to:
> 
> >> No need.  Let the user do it themselves. Similar to what we did for
> >> macaddr's back in the summer. 
> 
> > Yeah, it can be user-defined (or a contrib), no question about it, and for
> > people who have more than one table of networks, it will _have_ to be
> > user-defined.
> 
> It seems clear to me that this mapping is best left to the user.
> 
> A more interesting question is whether the system needs to provide any
> assisting functions that aren't there now.  The lookup function you guys
> are postulating seems like it would be (in the simple cases)
>     create function my_network(inet) returns cidr as
>     'select network from my_networks where ???'
> Maybe it's too late at night, but I'm having a hard time visualizing
> what the ??? condition is and whether any additional system-level
> functions are needed to make it simple/efficient.
I don't think we need this ASAP for 7.1.  Let's get the basic stuff
working from a "least surprise" standpoint, and see what the user base
comes up with.  I really think your proposal from earlier tonite is
the way to go, at least from my perspective. 

Thanks again.

LER

> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Alex Pilosov <alex@pilosoft.com> [001027 21:36]:
> On Fri, 27 Oct 2000, Larry Rosenman wrote:
> 
> > Not necessarily, especially for novices.  Some people may want to
> > store the netmask with the IP of a host (think ifconfig being
> > AUTOGEN'd). 
> For a single host? Or for a network of hosts? But yes, I see your point if
> a single host has x interfaces, and you are autogenerating ifconfig, with
> my proposal, you'd need to insert each network into networks table.
Or a table of Routers, listed by IP's.  I want to be able to
efficently store the interface name, IP, Mask.  With your proposal, I
can't store it as one row in one table.  With Tom's proposal, I can. 

> 
> > > 99% of people who would be storing IP addresses into postgres database
> > > really do not know nor care what is a netmask on that IP. Only people who
> > > would care are ones who store their _internal_ addresses (read: addresses
> > > used on networks they manage).  There is usually a very limited number of
> > > such networks (<1000). 
> > I disagree.  I'm an ISP, and the network engineer for same.  I have a
> > BOATLOAD of Netblocks from ARIN and providers in a BUNCH of sizes.  I
> > need to subnet them out to customers and for internal use.  I like
> > Tom's latest proposal. This one LOSES functionality for ME. 
> Explain how does it lose functionality?
I may need to list an interface in their net, with their netmask, but
not have it in my networks table.  I don't think that the system
should supply a networks table, per se.   I have much more than 1000's
networks in my shop.  Please don't FORCE me to your model.  I like
Tom's proposal, especially from the "least surprise" aspects.  
> 
> > > It makes no sense to have in database both 10.0.0.1/24 and 10.0.0.2/16.
> > > None whatsoever.
> > Not necessarily, especially with RFC1918 addresses, and reuse within
> > different unconnected networks of the SAME enterprise. 
> Makes no sense to have them in one table, anyway, I stand corrected.  
> For people in situation you describe, you can have a second table of
> networks, and second function to look up networks in that table. 
See above.  Please don't force me to your paradigm. 
> 
> > > This does NOT apply to CIDR datatype, as there are real applications (such
> > > as storing routing tables) where you would care about netmask, but won't
> > > care about a host part. 
> > > 
> > > What I am suggesting is we do the following:
> > > a) inet will NOT have a netmask
> > Please DONT.  See above.
> > > 
> > > b) all the fancy comparison functions on inet should be deleted. 
> > > (leave only > >= = <= <)
> > > 
> > Maybe.  I think they should stay, but I'm one lowly network engineer.
> > > c) the only things you can do on inet is to convert it to 4 octets (of
> > > int1), to a int8, and to retrieve its network from a table of networks.
> > > 
> > > d) have a table, 'networks' (or any other name, maybe pg_networks?) which
> > > would have one column 'network', with type cidr.
> > > create table networks (network cidr not null primary key)
> > Why?
> Because netmask is a property of a network, not of an IP address.
> 
> > > e) have a function network(inet) which would look up the address in a
> > > table of networks using longest-prefix-match. I.E. something similar to:
> > No need.  Let the user do it themselves. Similar to what we did for
> > macaddr's back in the summer. 
> Yeah, it can be user-defined (or a contrib), no question about it, and for
> people who have more than one table of networks, it will _have_ to be
> user-defined.
> 
> Actually, that's probably what I'll end up doing on my own. 
> 

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Larry Rosenman wrote:

> Not necessarily, especially for novices.  Some people may want to
> store the netmask with the IP of a host (think ifconfig being
> AUTOGEN'd). 
For a single host? Or for a network of hosts? But yes, I see your point if
a single host has x interfaces, and you are autogenerating ifconfig, with
my proposal, you'd need to insert each network into networks table.

> > 99% of people who would be storing IP addresses into postgres database
> > really do not know nor care what is a netmask on that IP. Only people who
> > would care are ones who store their _internal_ addresses (read: addresses
> > used on networks they manage).  There is usually a very limited number of
> > such networks (<1000). 
> I disagree.  I'm an ISP, and the network engineer for same.  I have a
> BOATLOAD of Netblocks from ARIN and providers in a BUNCH of sizes.  I
> need to subnet them out to customers and for internal use.  I like
> Tom's latest proposal. This one LOSES functionality for ME. 
Explain how does it lose functionality?

> > It makes no sense to have in database both 10.0.0.1/24 and 10.0.0.2/16.
> > None whatsoever.
> Not necessarily, especially with RFC1918 addresses, and reuse within
> different unconnected networks of the SAME enterprise. 
Makes no sense to have them in one table, anyway, I stand corrected.  
For people in situation you describe, you can have a second table of
networks, and second function to look up networks in that table. 

> > This does NOT apply to CIDR datatype, as there are real applications (such
> > as storing routing tables) where you would care about netmask, but won't
> > care about a host part. 
> > 
> > What I am suggesting is we do the following:
> > a) inet will NOT have a netmask
> Please DONT.  See above.
> > 
> > b) all the fancy comparison functions on inet should be deleted. 
> > (leave only > >= = <= <)
> > 
> Maybe.  I think they should stay, but I'm one lowly network engineer.
> > c) the only things you can do on inet is to convert it to 4 octets (of
> > int1), to a int8, and to retrieve its network from a table of networks.
> > 
> > d) have a table, 'networks' (or any other name, maybe pg_networks?) which
> > would have one column 'network', with type cidr.
> > create table networks (network cidr not null primary key)
> Why?
Because netmask is a property of a network, not of an IP address.

> > e) have a function network(inet) which would look up the address in a
> > table of networks using longest-prefix-match. I.E. something similar to:
> No need.  Let the user do it themselves. Similar to what we did for
> macaddr's back in the summer. 
Yeah, it can be user-defined (or a contrib), no question about it, and for
people who have more than one table of networks, it will _have_ to be
user-defined.

Actually, that's probably what I'll end up doing on my own. 




Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
Please read below if the whole thing with inet/cidr doesn't make you puke
yet ;) The semi-longish proposal is at the bottom.

On Fri, 27 Oct 2000, Tom Lane wrote:

> Alex Pilosov <alex@pilosoft.com> writes:
> > We should have as much error-checking as possible.
> 
> How so?  Without a netmask you have no way to know if it's a broadcast
> address or not. 10.0.0.255/32 might be a perfectly valid host address
> in, say, 10.0/16.  But 10.0.0.255/24 is recognizably the broadcast
> address for 10.0.0/24 (and not for any other network...)
Right, that's what I'm trying to say: It shouldn't allow you to use
10.0.0.255/24 as a host address, but it should allow you to use 
10.0.0.255/16 

> > (ie. broadcast() function must return a value with /32 mask)
> 
> I don't disagree with that part, but that's only because I see
> broadcast() as mainly a display convenience.  If we had a larger and
> more thoroughly worked out set of inet/cidr operators, I'd be inclined
> to argue that broadcast('10.0.0.0/24') should yield 10.0.0.255/24 for
> computational convenience.  Then we'd need to offer a separate function
> that would let you strip off the netmask for display purposes (actually
> host() would do for that...)


Actually, now that I think longer about the whole scheme in terms of
actual IP experience, here are my ideas:
a) inet is crock. I don't know anyone who would need to _care_ about a
netmask of a host, who wouldn't have a lookup table of networks/masks.
(Think /etc/hosts, and /etc/netmasks).

Storing a netmask of a network in a inet actually violates the relational
constraints: netmask is not a property of an IP address, its a property of
a network.

99% of people who would be storing IP addresses into postgres database
really do not know nor care what is a netmask on that IP. Only people who
would care are ones who store their _internal_ addresses (read: addresses
used on networks they manage).  There is usually a very limited number of
such networks (<1000). 

It makes no sense to have in database both 10.0.0.1/24 and 10.0.0.2/16.
None whatsoever.

This does NOT apply to CIDR datatype, as there are real applications (such
as storing routing tables) where you would care about netmask, but won't
care about a host part. 

What I am suggesting is we do the following:
a) inet will NOT have a netmask

b) all the fancy comparison functions on inet should be deleted. 
(leave only > >= = <= <)

c) the only things you can do on inet is to convert it to 4 octets (of
int1), to a int8, and to retrieve its network from a table of networks.

d) have a table, 'networks' (or any other name, maybe pg_networks?) which
would have one column 'network', with type cidr.
create table networks (network cidr not null primary key)

e) have a function network(inet) which would look up the address in a
table of networks using longest-prefix-match. I.E. something similar to:

select network from networks 
where $1<<network 
order by network_prefix(network)
desc limit 1;


I realise that this sounds a little bit strange after all the arguments
about inet, but if you think about it, this is the only sane way to deal
with these datatypes. 

Right now, the datatypes we have look and sound pretty but are pretty much
useless in reality. Yes, it is nice to be able to store a netmask with
every IP address, it is useless in reality. (Yes, please, someone tell me
if you are using inet with netmasks and you actually like it).


I'd especially like to get input of Marc on this, as he's both a core team
member and has actual networking background...Oh yeah, if Marc can comment
on whether 10/8 or 10.0.0.0/8 is a proper way to represent a network, it'd
be great too :)





Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Alex Pilosov <alex@pilosoft.com> [001027 21:20]:
> Please read below if the whole thing with inet/cidr doesn't make you puke
> yet ;) The semi-longish proposal is at the bottom.
> 
> On Fri, 27 Oct 2000, Tom Lane wrote:
[snip]
> Actually, now that I think longer about the whole scheme in terms of
> actual IP experience, here are my ideas:
> a) inet is crock. I don't know anyone who would need to _care_ about a
> netmask of a host, who wouldn't have a lookup table of networks/masks.
> (Think /etc/hosts, and /etc/netmasks).
> 
> Storing a netmask of a network in a inet actually violates the relational
> constraints: netmask is not a property of an IP address, its a property of
> a network.
Not necessarily, especially for novices.  Some people may want to
store the netmask with the IP of a host (think ifconfig being
AUTOGEN'd). 

> 
> 99% of people who would be storing IP addresses into postgres database
> really do not know nor care what is a netmask on that IP. Only people who
> would care are ones who store their _internal_ addresses (read: addresses
> used on networks they manage).  There is usually a very limited number of
> such networks (<1000). 
I disagree.  I'm an ISP, and the network engineer for same.  I have a
BOATLOAD of Netblocks from ARIN and providers in a BUNCH of sizes.  I
need to subnet them out to customers and for internal use.  I like
Tom's latest proposal. This one LOSES functionality for ME. 
> 
> It makes no sense to have in database both 10.0.0.1/24 and 10.0.0.2/16.
> None whatsoever.
Not necessarily, especially with RFC1918 addresses, and reuse within
different unconnected networks of the SAME enterprise. 
> 
> This does NOT apply to CIDR datatype, as there are real applications (such
> as storing routing tables) where you would care about netmask, but won't
> care about a host part. 
> 
> What I am suggesting is we do the following:
> a) inet will NOT have a netmask
Please DONT.  See above.
> 
> b) all the fancy comparison functions on inet should be deleted. 
> (leave only > >= = <= <)
> 
Maybe.  I think they should stay, but I'm one lowly network engineer.
> c) the only things you can do on inet is to convert it to 4 octets (of
> int1), to a int8, and to retrieve its network from a table of networks.
> 
> d) have a table, 'networks' (or any other name, maybe pg_networks?) which
> would have one column 'network', with type cidr.
> create table networks (network cidr not null primary key)
Why?
> 
> e) have a function network(inet) which would look up the address in a
> table of networks using longest-prefix-match. I.E. something similar to:
No need.  Let the user do it themselves. Similar to what we did for
macaddr's back in the summer. 
> 
> select network from networks 
> where $1<<network 
> order by network_prefix(network)
> desc limit 1;
> 
> 
> I realise that this sounds a little bit strange after all the arguments
> about inet, but if you think about it, this is the only sane way to deal
> with these datatypes. 
> 
> Right now, the datatypes we have look and sound pretty but are pretty much
> useless in reality. Yes, it is nice to be able to store a netmask with
> every IP address, it is useless in reality. (Yes, please, someone tell me
> if you are using inet with netmasks and you actually like it).
> 
See above. 
> 
> I'd especially like to get input of Marc on this, as he's both a core team
> member and has actual networking background...Oh yeah, if Marc can comment
> on whether 10/8 or 10.0.0.0/8 is a proper way to represent a network, it'd
> be great too :)
> 
> 

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Larry Rosenman <ler@lerctr.org> writes:
> Fine, but host() rejects CIDR types right now....

What's your point?  network() doesn't behave the way you want right now,
either.
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Tom Lane wrote:

> BTW, does it strike anyone else as peculiar that the host(),
> broadcast(), network(), and netmask() functions yield results
> of type text, rather than type inet?  Seems like it'd be considerably
> more useful if they returned values of type inet with masklen = 32
> (except for network(), which would keep the original masklen while
> coercing bits to its right to 0).
Yep, absolutely. 

> Given the current proposal that inet_out should always display all 4
> octets, and the existing fact that inet_out suppresses display of
> a /32 netmask, the textual display of SELECT host(...) etc would
> remain the same as it is now.  But AFAICS you could do more with
> an inet-type result value, like say compare it to other inet or cidr
> values ...
> Comments?  Why was it done this way, anyway?



Second proposal: what to do about INET/CIDR

From
Tom Lane
Date:
Sigh ... I was really hoping not to get drawn into fixing these issues
for 7.1, but ...

It seems like much of the problem is that there isn't any easy way to
choose between CIDR-style display format ('127.1/16') and INET-style
format ('127.1.0.0/16').  We need to bite the bullet and add conversion
functions, so that people can pick which they want.

Picking and choosing among the ideas discussed, here's my stab at a
complete proposal:

1. CIDR-type values will be displayed in "abbreviated" format, eg  "127.1/16".  Since a CIDR value is no longer allowed
tohave any  nonzero bits to the right of the mask, no information is lost by  abbreviation.  The /n will appear even
whenit is 32.
 

2. INET-type values will always be displayed with all octets, eg  "127.1.0.0/16".  The /n part will be suppressed from
display if it is 32.  INET will accept any octet pattern as an address  together with any netmask length from 1 to 32.
 

3. We will add explicit functions cidr(inet) and inet(cidr) to force  the data type to one or the other style, thus
allowingselection  of either display style.  Note that cidr(inet) will raise an error  if given something with
nonzeroesto the right of the netmask.
 

4. The function host(inet) will now return inet not text.  It will  take the address octets of the given value but
forcethe netmask to 32  and the display type to INET.  So for example host('127.1/16'::cidr)  will yield
'127.1.0.0/32'::inet,which if displayed will appear  as just '127.1.0.0', per item 2.
 

5. The function broadcast(inet) will now return inet not text.  It  will take the given address octets and force the
bitsto the right  of the netmask to 1.  The display type will be set to inet.  After  more thought about my last
message,I am inclined to have it return  the same masklength as the input, so for example broadcast('127.1/16')  would
yield'127.1.255.255/16'::inet.  If you want the broadcast  address displayed without a netmask notation, you'd need to
write host(broadcast(foo)).  Alternatively, we could say that broadcast()  always returns masklen 32, but I think this
losesvaluable  functionality.
 

6. The function network(inet) will now return cidr not text.  The result  has the same masklen as the input, with bits
tothe right of the mask  zeroed to ensure it is a valid cidr value.  The display type will be  set to cidr.  For
example,network('127.1.2.3/16') will yield  '127.1/16'::cidr.  To get this result displayed in inet format, you'd
writeinet(network(foo)) --- yielding '127.1.0.0/16'.  If you want it  displayed with no netmask, write
host(network(foo))--- result  '127.1.0.0'.
 

7. The function netmask(inet) will now return inet not text.  It will  return octets with 1s in the input's netmask, 0s
tothe right, and  output display type and masklen set to inet and 32.  For example,  netmask('127.1/16') =
'255.255.0.0/32'::inetwhich will display as  '255.255.0.0'.  (I suppose a really anal definition would keep the  input
masklen,forcing you to write host(netmask(foo)) to get a  display without "/n".  But I don't see any value in that for
netmasks.)

8. Because we still consider inet and cidr to be binary-equivalent types,  all of these functions will be applied to
eitherinet or cidr columns  without any type conversion.  (In other words, cidr(inet) and  inet(cidr) will only be
appliedif *explicitly* invoked.)  I am not  convinced whether this is a good thing.  In this proposal, no system
functionexcept display will care whether its input is inet or cidr,  so the lack of conversion doesn't matter.  But in
thelong run it  might be better to remove the binary-equivalence.  Then, for example,  host(cidr) would be implemented
ashost(inet(cidr)), costing an extra  function call per operation.  Right now I don't think we need to pay  that price,
butmaybe someday we will.
 

Thoughts?
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
I wrote:
> There is no subset type that corresponds to "valid host addresses
> only" --- if there were, it would be a subset of INET but would have
> no valid values in common with CIDR.

I take that back --- CIDR accepts w.x.y.z/32 for any w.x.y.z, which
would include valid host addresses.  (But perhaps it should only
accept netmasks shorter than 32 bits?  Not sure if "CIDR" is commonly
understood to be network specs only, or network and host specs.)
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 17:54]:
> Alex Pilosov <alex@pilosoft.com> writes:
> > On Fri, 27 Oct 2000, Tom Lane wrote:
> >> BTW, does it strike anyone else as peculiar that the host(),
> >> broadcast(), network(), and netmask() functions yield results
> >> of type text, rather than type inet?
> 
> > I absolutely agree, except for network(), which should return cidr.
> 
> We could do that, but if we did, it would print out per CIDR format
> (eg, '192.1/16') whereas both you and Larry have been saying you want
> a way to produce '192.1.0.0/16'.  Perhaps we need two functions, one
> to produce the network in CIDR notation and one to produce it in INET
> notation.
I'd agree with this.
> 
> For that matter, perhaps we should not change host() to accept CIDR
> but instead provide a separate function that does what I proposed
> host() should do with a CIDR.  Not sure.
> 
> > As I mentioned in another email, should inet datatype really care whether
> > host part is all-ones or all-zeros and reject that?
> 
> I'm inclined to think not, partially because that would mean that the
> results of broadcast() and network() could *NOT* be considered valid
> INET values.
True.
> 
> The way I'm visualizing this, INET is a generalized type that will store
> any 4-octet address plus any netmask width from 1 to 32.  This includes
> not only host addresses, but network specs and broadcast addresses.
> CIDR is a subset type that only accepts valid network specs (ie, no
> nonzero address bits to the right of the netmask).  There is no subset
> type that corresponds to "valid host addresses only" --- if there were,
> it would be a subset of INET but would have no valid values in common
> with CIDR.  We could make such a type but I dunno if it's worth the
> trouble.
I believe this is true.  Now if we could get the output stuff so there
are BOTH ways of displaying the data (we seem to need both, from the
statements we get each time this has been brought up), such that you
can freely move between the 4-octet and short-octet (for lack of a
better term) version of a CIDR network spec. 

Thanks for any consideration, and if this could make 7.1, I'd be most
appreciative...

Larry

> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Second proposal: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001027 20:45]:
> Sigh ... I was really hoping not to get drawn into fixing these issues
> for 7.1, but ...
[SNIP]
Works WELL for me.  THANK YOU, Tom.

LER

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
one more small request:

int8_inet(inet) and inet_int8(int8): functions to convert an inet to an
int8 and back. (not an int4, since postgres int4s are signed)

This allows me to do some additional manipulations on values. (ie. given a
host, determine its default gateway, for us, it is always first host on
that network, this could be implemented as inet_int8(int8_inet(network(x))+1), 
or splitting a cidr into two halves, 

-alex








Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Tom Lane wrote:

> A more interesting question is whether the system needs to provide any
> assisting functions that aren't there now.  The lookup function you guys
> are postulating seems like it would be (in the simple cases)
>     create function my_network(inet) returns cidr as
>     'select network from my_networks where ???'
as in my mail:
select network from my_network where network>>$1 order by
network_prefix(network) desc limit 1;

(i.e. if many networks cover the ip address, pick the one with longest
prefix). The only hard question here, how to properly index this table.
This sounds like a perfect application of user-defined index method. 
I need to look up documentation on how they work...


However, this probably won't pose a major problem in production: the
networks table will be relatively small. 

> Maybe it's too late at night, but I'm having a hard time visualizing
> what the ??? condition is and whether any additional system-level
> functions are needed to make it simple/efficient.

Actually, you can scratch my proposal. I realise it could be inconvenient
for some people.

I'll be probably putting all my hosts as inet::xxx/32, have the above
lookup function to get real network, and do operations on that.





Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
>>>> e) have a function network(inet) which would look up the address in a
>>>> table of networks using longest-prefix-match. I.E. something similar to:

>> No need.  Let the user do it themselves. Similar to what we did for
>> macaddr's back in the summer. 

> Yeah, it can be user-defined (or a contrib), no question about it, and for
> people who have more than one table of networks, it will _have_ to be
> user-defined.

It seems clear to me that this mapping is best left to the user.

A more interesting question is whether the system needs to provide any
assisting functions that aren't there now.  The lookup function you guys
are postulating seems like it would be (in the simple cases)create function my_network(inet) returns cidr as'select
networkfrom my_networks where ???'
 
Maybe it's too late at night, but I'm having a hard time visualizing
what the ??? condition is and whether any additional system-level
functions are needed to make it simple/efficient.
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
On Fri, 27 Oct 2000, Tom Lane wrote:

> BTW, does it strike anyone else as peculiar that the host(),
> broadcast(), network(), and netmask() functions yield results
> of type text, rather than type inet?  Seems like it'd be considerably
> more useful if they returned values of type inet with masklen = 32
> (except for network(), which would keep the original masklen while
> coercing bits to its right to 0).
I absolutely agree, except for network(), which should return cidr.
(after all, this is the network).

As I mentioned in another email, should inet datatype really care whether
host part is all-ones or all-zeros and reject that? It would make sense to
me (10.0.0.0/8::inet is not a valid address, but 10.0.0.0/8::cidr is), but
it would break some people's scripts...

I'm talking here from a perspective of a network provider with P
knowledge...I'm sure Marc can chime in here...
-alex





Re: Summary: what to do about INET/CIDR

From
Peter Eisentraut
Date:
Tom Lane writes:

> Hm.  I don't see any really good reason why host() rejects CIDR input
> in the first place.  What's wrong with producing the host address
> that corresponds to extending the CIDR network address with zeroes?

Because it's semantically wrong.  It's just as wrong as converting DATE to
TIMESTAMP by setting the time to zero.  -- And we actually do this...

-- 
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/



Re: Second proposal: what to do about INET/CIDR

From
Peter Eisentraut
Date:
Tom Lane writes:

> 3. We will add explicit functions cidr(inet) and inet(cidr) to force
>    the data type to one or the other style, thus allowing selection
>    of either display style.  Note that cidr(inet) will raise an error
>    if given something with nonzeroes to the right of the netmask.

Not sure if using functions that look like a cast to control output format
is a good idea.  The conversion inet => cidr seems most naturally left
with the network() function.  The other conversion is not well-defined.  
(You could define it in several reasonable ways, but that still doesn't
make it "well".)  ISTM that you'd really need some function build_inet(a
cidr, b inet) returns inet, where b does not have a network and can
somehow be fitted into network a.

Actually, let's sign up Karel to write to_char(inet) and to_char(cidr).

> But in the long run it might be better to remove the
> binary-equivalence.

I say kill it ASAP.  I don't think there was ever a good reason for this
besides implementation convenience; and the troubles it has caused are
without end.

-- 
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/



Re: Summary: what to do about INET/CIDR

From
"Dominic J. Eidson"
Date:
On Fri, 27 Oct 2000, Alex Pilosov wrote:

> > BTW, does it strike anyone else as peculiar that the host(),
> > broadcast(), network(), and netmask() functions yield results
> > of type text, rather than type inet?  Seems like it'd be considerably
> > more useful if they returned values of type inet with masklen = 32
> > (except for network(), which would keep the original masklen while
> > coercing bits to its right to 0).
> I absolutely agree, except for network(), which should return cidr.
> (after all, this is the network).
> 
> As I mentioned in another email, should inet datatype really care whether
> host part is all-ones or all-zeros and reject that? It would make sense to
> me (10.0.0.0/8::inet is not a valid address, but 10.0.0.0/8::cidr is), but
> it would break some people's scripts...

How about letting inet just be a "simple" storage type for four octets
seperated by periods. (Along the line of (0-255) . (0-255) . (0-255) . (0-255) )

The only conversion function there would be that operates on inet is
cidr(inet) - which returns the contents of the tuple, with a /32.
Alternately, for those who think we absolutely need something more
complicated (I don't think it's neeccesary), something along the lines of:

cidr('10.20.23.252' => '10.20.23.252/32'
cidr('10.20.23.0') => '10.20.23/24' (or '10.20.23.0/24')
cidr('10.20.0.0') => '10.20/16' (or '10.20.0.0/16')
cidr('10.0.0.0') => '10/8' (or '10.0.0.0/8')

Although one should put a comment/warning in the documentation that cidr()
assumes subnets to be on an octet boundary. (Which is the norm with inet
stuff - cidr was created specifically to get away from
subnet-on-octet-boundaries.)

Slight digression - on the discussion whether it's 127/8, or 127.0.0.0/8 -
both are accepted in most applications nowadays. But back to the issue
at hand...

Then let the cidr data type be for anything more advanced - like for
storing subnets on non-octet boundaries etc, and have host(),
broadcast(), network(), and netmask() functions. host() would return the
IP with a /32 mask - and inet(cidr) would just return the IP, without a
mask.

> I'm talking here from a perspective of a network provider with P
> knowledge...I'm sure Marc can chime in here...

So am I.

-- 
Dominic J. Eidson                                       "Baruk Khazad! Khazad ai-menu!" - Gimli
-------------------------------------------------------------------------------
http://www.the-infinite.org/              http://www.the-infinite.org/~dominic/



Re: Second proposal: what to do about INET/CIDR

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Tom Lane writes:
>> 3. We will add explicit functions cidr(inet) and inet(cidr) to force
>> the data type to one or the other style, thus allowing selection
>> of either display style.  Note that cidr(inet) will raise an error
>> if given something with nonzeroes to the right of the netmask.

> Not sure if using functions that look like a cast to control output format
> is a good idea.  The conversion inet => cidr seems most naturally left
> with the network() function.  The other conversion is not well-defined.  
> (You could define it in several reasonable ways, but that still doesn't
> make it "well".)

Good point: cidr() is exactly the same as network() under my proposal,
so we don't need a separate function for that.

While inet() and host() as proposed may be morally impure, they're no
worse than date->timestamp and similar conversions that we have in
abundance.  I do not agree that they are ill-defined --- the spec
I wrote seems perfectly clear.

Would you be happier if inet() and host() were defined to produce
textual representations --- respectively "w.x.y.z/n" and "w.x.y.z"
rather than actual INET values?  That seems like it'd still solve
the demand for being able to extract these specific representations,
without opening up the quagmire of whether these values are legitimate
INET values.
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Larry Rosenman <ler@lerctr.org> [001028 02:23]:
> I don't think we need this ASAP for 7.1.  Let's get the basic stuff
> working from a "least surprise" standpoint, and see what the user base
> comes up with.  I really think your proposal from earlier tonite is
> the way to go, at least from my perspective. 
> 
> Thanks again.
What was the final outcome?  Will Tom's proposal make 7.1? 

(Do I need to learn how to code backend stuff?)

LER
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Larry Rosenman <ler@lerctr.org> writes:
> What was the final outcome?

I don't think we'd quite agreed what to do.  The proposed code changes
are not large, we just need a consensus on what the behavior ought to
be.

Since a couple of people objected to the idea of using casts to control
the output format, here is a strawman Plan C for discussion.  This
differs from my last proposal in that the inet() and cidr() pseudo
cast functions are gone, and there are two functions returning text
values that can be used if you don't like the default display formats.

1. CIDR-type values will be displayed in "abbreviated" format, eg  "127.1/16".  Since a CIDR value is no longer allowed
tohave any  nonzero bits to the right of the mask, no information is lost by  abbreviation.  The /n will appear even
whenit is 32.
 

2. INET-type values will always be displayed with all octets, eg  "127.1.0.0/16".  The /n part will be suppressed from
display if it is 32.  INET will accept any octet pattern as an address  together with any netmask length from 1 to 32.
 

3. The function host(inet) will return a text representation of  just the IP part of an INET or CIDR value, eg,
"127.1.0.0". All four octets will always appear, the netmask will never appear.  (This is the same as its current
behavior,I think.)
 

4. A new function text(inet) will return a text representation of  both the IP and netmask parts of an INET or CIDR
value,eg,  "127.1.0.0/16".  Unlike the default display conversions, all four  octets and the netmask length will always
appearin the result.  Note that the system will consider this function to be a typecast,  so the same result can be
gottenwith inetval::text or  CAST(inetval AS text).
 

[ the rest is the same as in my last proposal: ]

5. The function broadcast(inet) will now return inet not text.  It  will take the given address octets and force the
bitsto the right  of the netmask to 1.  The display type will be set to inet.  I am  inclined to have it return the
samemasklength as the input, so for  example broadcast('127.1/16') would yield '127.1.255.255/16'::inet.  If you want
thebroadcast address displayed without a netmask  notation, you'd need to write host(broadcast(foo)).  Alternatively,
wecould say that broadcast() always returns masklen 32, but I think  this loses valuable functionality.
 

6. The function network(inet) will now return cidr not text.  The result  has the same masklen as the input, with bits
tothe right of the mask  zeroed to ensure it is a valid cidr value.  The display type will be  set to cidr.  For
example,network('127.1.2.3/16') will yield  '127.1/16'::cidr.  To get this result displayed in a different  format,
writehost(network(foo)) or text(network(foo)).
 

7. The function netmask(inet) will now return inet not text.  It will  return octets with 1s in the input's netmask, 0s
tothe right, and  output display type and masklen set to inet and 32.  For example,  netmask('127.1/16') =
'255.255.0.0/32'::inetwhich will display as  '255.255.0.0'.  (I suppose a really anal definition would keep the  input
masklen,forcing you to write host(netmask(foo)) to get a  display without "/n".  But I don't see any value in that for
netmasks.)

8. Because we still consider inet and cidr to be binary-equivalent types,  all of these functions can be applied to
eitherinet or cidr columns.
 

Comments?
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
Works for me.....

LER

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Alex Pilosov
Date:
Agreed with all of it, but how about incorporating conversion from inet
to int8? (first octet*256*256*256+second octet*256*256+third
octet*256+fourth octet). 

This will allow to do a lot of magic with addresses using plain math.

Also, I'd still like netmask_length, length of netmask in bits.

-alex

On Fri, 3 Nov 2000, Tom Lane wrote:

> 5. The function broadcast(inet) will now return inet not text.  It
>    will take the given address octets and force the bits to the right
>    of the netmask to 1.  The display type will be set to inet.  I am
>    inclined to have it return the same masklength as the input, so for
>    example broadcast('127.1/16') would yield '127.1.255.255/16'::inet.
>    If you want the broadcast address displayed without a netmask
>    notation, you'd need to write host(broadcast(foo)).  Alternatively,
>    we could say that broadcast() always returns masklen 32, but I think
>    this loses valuable functionality.
> 
> 6. The function network(inet) will now return cidr not text.  The result
>    has the same masklen as the input, with bits to the right of the mask
>    zeroed to ensure it is a valid cidr value.  The display type will be
>    set to cidr.  For example, network('127.1.2.3/16') will yield
>    '127.1/16'::cidr.  To get this result displayed in a different
>    format, write host(network(foo)) or text(network(foo)).
> 
> 7. The function netmask(inet) will now return inet not text.  It will
>    return octets with 1s in the input's netmask, 0s to the right, and
>    output display type and masklen set to inet and 32.  For example,
>    netmask('127.1/16') = '255.255.0.0/32'::inet which will display as
>    '255.255.0.0'.  (I suppose a really anal definition would keep the
>    input masklen, forcing you to write host(netmask(foo)) to get a
>    display without "/n".  But I don't see any value in that for
>    netmasks.)
> 
> 8. Because we still consider inet and cidr to be binary-equivalent types,
>    all of these functions can be applied to either inet or cidr columns.
> 
> Comments?
> 
>             regards, tom lane
> 
> 



Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Alex Pilosov <alex@pilosoft.com> [001103 20:47]:
> Agreed with all of it, but how about incorporating conversion from inet
> to int8? (first octet*256*256*256+second octet*256*256+third
> octet*256+fourth octet). 
> 
> This will allow to do a lot of magic with addresses using plain math.
> 
> Also, I'd still like netmask_length, length of netmask in bits.
masklen(inet) is there:
int4      | masklen             | inet 

from a \df. 

Can we also get it to work on cidr (or allow cast from inet to cidr).


> 
> -alex
> 
> On Fri, 3 Nov 2000, Tom Lane wrote:
> 
> > 5. The function broadcast(inet) will now return inet not text.  It
> >    will take the given address octets and force the bits to the right
> >    of the netmask to 1.  The display type will be set to inet.  I am
> >    inclined to have it return the same masklength as the input, so for
> >    example broadcast('127.1/16') would yield '127.1.255.255/16'::inet.
> >    If you want the broadcast address displayed without a netmask
> >    notation, you'd need to write host(broadcast(foo)).  Alternatively,
> >    we could say that broadcast() always returns masklen 32, but I think
> >    this loses valuable functionality.
> > 
> > 6. The function network(inet) will now return cidr not text.  The result
> >    has the same masklen as the input, with bits to the right of the mask
> >    zeroed to ensure it is a valid cidr value.  The display type will be
> >    set to cidr.  For example, network('127.1.2.3/16') will yield
> >    '127.1/16'::cidr.  To get this result displayed in a different
> >    format, write host(network(foo)) or text(network(foo)).
> > 
> > 7. The function netmask(inet) will now return inet not text.  It will
> >    return octets with 1s in the input's netmask, 0s to the right, and
> >    output display type and masklen set to inet and 32.  For example,
> >    netmask('127.1/16') = '255.255.0.0/32'::inet which will display as
> >    '255.255.0.0'.  (I suppose a really anal definition would keep the
> >    input masklen, forcing you to write host(netmask(foo)) to get a
> >    display without "/n".  But I don't see any value in that for
> >    netmasks.)
> > 
> > 8. Because we still consider inet and cidr to be binary-equivalent types,
> >    all of these functions can be applied to either inet or cidr columns.
> > 
> > Comments?
> > 
> >             regards, tom lane
> > 
> > 

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Peter Eisentraut
Date:
Tom Lane writes:

> 3. The function host(inet) will return a text representation of
>    just the IP part of an INET or CIDR value, eg, "127.1.0.0".
>    All four octets will always appear, the netmask will never appear.
>    (This is the same as its current behavior, I think.)

I think there was definite merit in the host() function returning inet, as
you originally proposed (if only for consistency with the proposed changes
to network() and broadcast()).

A separate function for formatting output seems necessary, but if we don't
reach an agreement though, it ought to work to cast CIDR to INET to get
all four octets, no?

> 4. A new function text(inet) will return a text representation of
>    both the IP and netmask parts of an INET or CIDR value, eg,
>    "127.1.0.0/16".  Unlike the default display conversions, all four
>    octets and the netmask length will always appear in the result.
>    Note that the system will consider this function to be a typecast,
>    so the same result can be gotten with inetval::text or
>    CAST(inetval AS text).

I think the typecast-to-text representation of CIDR should be visually the
same as the normal representation.

-- 
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/



Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> A separate function for formatting output seems necessary, but if we don't
> reach an agreement though, it ought to work to cast CIDR to INET to get
> all four octets, no?

Uh, weren't you one of the people objecting to relying on cidr-to-inet
casts to control formatting?

> I think the typecast-to-text representation of CIDR should be visually the
> same as the normal representation.

Well, we need *some* way to extract a representation like "w.x.y.z/n".
If you don't like text() as the name of that formatting function,
suggest another name...
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Peter Eisentraut
Date:
Tom Lane writes:

> Peter Eisentraut <peter_e@gmx.net> writes:
> > A separate function for formatting output seems necessary, but if we don't
> > reach an agreement though, it ought to work to cast CIDR to INET to get
> > all four octets, no?
> 
> Uh, weren't you one of the people objecting to relying on cidr-to-inet
> casts to control formatting?

I didn't like the use of the to-text casts to control formatting, but if
an existing cast would "just handle it", then why not?

> > I think the typecast-to-text representation of CIDR should be visually the
> > same as the normal representation.
> 
> Well, we need *some* way to extract a representation like "w.x.y.z/n".
> If you don't like text() as the name of that formatting function,
> suggest another name...

all_octets(cidr)::text maybe?

-- 
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/



Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Peter Eisentraut <peter_e@gmx.net> [001105 07:08]:
> Tom Lane writes:
> 
> > Peter Eisentraut <peter_e@gmx.net> writes:
> > > A separate function for formatting output seems necessary, but
> > > if we don't reach an agreement though, it ought to work to cast
> > > CIDR to INET to get all four octets, no?
> > 
> > Uh, weren't you one of the people objecting to relying on
> > cidr-to-inet casts to control formatting?
> 
> I didn't like the use of the to-text casts to control formatting,
> but if an existing cast would "just handle it", then why not?

> 
> > > I think the typecast-to-text representation of CIDR should be
> > > visually the same as the normal representation.
> > 
> > Well, we need *some* way to extract a representation like
> > "w.x.y.z/n".  If you don't like text() as the name of that
> > formatting function, suggest another name...
> 
> all_octets(cidr)::text maybe?
Personally, I just want a way, guaranteed to work, to get all 4 octets
printed out for both CIDR and INET types.  If I need to cast to INET,
that's fine.  We also need to make sure that we can print all the
pieces out as well (masklen, broadcast, netmask, network). 

I really would like to see this resolved for 7.1, as I have a number
of apps that need to interface with NON-techies, and we need to print
out all 4 octets, as well as netmasks, etc.  PostgreSQL is the perfect
DB for the backend BECAUSE of the inet/cidr types.  Yes, I could write
convoluted PHP code to print out the stuff, but why should I when the
DB has all the information in a nice compact form, and a SELECT
statement could handle it? 

I do understand the philosophical problems, but we really are very
close.  Can we promise that we'll get this ironed out for 7.1? 

Thanks.

-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org US Mail: 1905
Steamboat Springs Drive, Garland, TX 75044-6749


Re: Summary: what to do about INET/CIDR

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
>> Well, we need *some* way to extract a representation like "w.x.y.z/n".
>> If you don't like text() as the name of that formatting function,
>> suggest another name...

> all_octets(cidr)::text maybe?

No, because that doesn't accurately describe what it does for inet
items --- those'd be shown with all octets anyway.  For inet, the
critical thing this function will do is force the netmask to be shown
even if it's /32.

Given that we are using host() for the function that shows just the
IP address part of an inet/cidr value, how about hostandmask() for
the function that always shows everything?

I still prefer text() though.
        regards, tom lane


Re: Summary: what to do about INET/CIDR

From
Larry Rosenman
Date:
* Tom Lane <tgl@sss.pgh.pa.us> [001109 10:30]:
> Peter Eisentraut <peter_e@gmx.net> writes:
> >> Well, we need *some* way to extract a representation like "w.x.y.z/n".
> >> If you don't like text() as the name of that formatting function,
> >> suggest another name...
> 
> > all_octets(cidr)::text maybe?
> 
> No, because that doesn't accurately describe what it does for inet
> items --- those'd be shown with all octets anyway.  For inet, the
> critical thing this function will do is force the netmask to be shown
> even if it's /32.
> 
> Given that we are using host() for the function that shows just the
> IP address part of an inet/cidr value, how about hostandmask() for
> the function that always shows everything?
> 
> I still prefer text() though.
What is the *PHILOSOPHICAL* objection to text() in this case?

It's a TEXT output? 

LER
> 
>             regards, tom lane
-- 
Larry Rosenman                      http://www.lerctr.org/~ler
Phone: +1 972-414-9812 (voice) Internet: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749