Clean up the INET-vs-CIDR situation. Get rid of the internal is_cidr flag
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Jan 2006 02:35:51 +0000 (02:35 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Jan 2006 02:35:51 +0000 (02:35 +0000)
and rely exclusively on the SQL type system to tell the difference between
the types.  Prevent creation of invalid CIDR values via casting from INET
or set_masklen() --- both of these operations now silently zero any bits
to the right of the netmask.  Remove duplicate CIDR comparison operators,
letting the type rely on the INET operators instead.

12 files changed:
doc/src/sgml/func.sgml
src/backend/optimizer/path/indxpath.c
src/backend/utils/adt/network.c
src/include/catalog/catversion.h
src/include/catalog/pg_amop.h
src/include/catalog/pg_cast.h
src/include/catalog/pg_operator.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h
src/include/utils/inet.h
src/test/regress/expected/opr_sanity.out
src/test/regress/sql/opr_sanity.sql

index a3eadb4bc400398137f02006a97e672765db4bc4..8f6f1ba392609e633cf555fa0a3070f627e4870a 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.302 2006/01/11 20:12:38 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.303 2006/01/26 02:35:48 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -6797,9 +6797,7 @@ SELECT pg_sleep(1.5);
    types.  The <function>host</function>,
    <function>text</function>, and <function>abbrev</function>
    functions are primarily intended to offer alternative display
-   formats. You can cast a text value to <type>inet</> using normal casting
-   syntax: <literal>inet(<replaceable>expression</>)</literal> or
-   <literal><replaceable>colname</>::inet</literal>.
+   formats.
   </para>
 
     <table id="cidr-inet-functions-table">
@@ -6843,6 +6841,13 @@ SELECT pg_sleep(1.5);
         <entry><literal>set_masklen('192.168.1.5/24', 16)</literal></entry>
         <entry><literal>192.168.1.5/16</literal></entry>
        </row>
+       <row>
+        <entry><literal><function>set_masklen</function>(<type>cidr</type>, <type>int</type>)</literal></entry>
+        <entry><type>cidr</type></entry>
+        <entry>set netmask length for <type>cidr</type> value</entry>
+        <entry><literal>set_masklen('192.168.1.0/24'::cidr, 16)</literal></entry>
+        <entry><literal>192.168.0.0/16</literal></entry>
+       </row>
        <row>
         <entry><literal><function>netmask</function>(<type>inet</type>)</literal></entry>
         <entry><type>inet</type></entry>
@@ -6875,6 +6880,13 @@ SELECT pg_sleep(1.5);
         <entry><literal><function>abbrev</function>(<type>inet</type>)</literal></entry>
         <entry><type>text</type></entry>
         <entry>abbreviated display format as text</entry>
+        <entry><literal>abbrev(inet '10.1.0.0/16')</literal></entry>
+        <entry><literal>10.1.0.0/16</literal></entry>
+       </row>
+       <row>
+        <entry><literal><function>abbrev</function>(<type>cidr</type>)</literal></entry>
+        <entry><type>text</type></entry>
+        <entry>abbreviated display format as text</entry>
         <entry><literal>abbrev(cidr '10.1.0.0/16')</literal></entry>
         <entry><literal>10.1/16</literal></entry>
        </row>
@@ -6890,6 +6902,22 @@ SELECT pg_sleep(1.5);
      </tgroup>
     </table>
 
+  <para>
+   Any <type>cidr</> value can be cast to <type>inet</> implicitly
+   or explicitly; therefore, the functions shown above as operating on
+   <type>inet</> also work on <type>cidr</> values.  (Where there are
+   separate functions for <type>inet</> and <type>cidr</>, it is because
+   the behavior should be different for the two cases.)
+   Also, it is permitted to cast an <type>inet</> value to <type>cidr</>.
+   When this is done, any bits to the right of the netmask are silently zeroed
+   to create a valid <type>cidr</> value.
+   In addition,
+   you can cast a text value to <type>inet</> or <type>cidr</>
+   using normal casting syntax: for example,
+   <literal>inet(<replaceable>expression</>)</literal> or
+   <literal><replaceable>colname</>::cidr</literal>.
+  </para>
+
   <para>
    <xref linkend="macaddr-functions-table"> shows the functions
    available for use with the <type>macaddr</type> type.  The function
index 9ec5911403f2ffbac1245ab896066975a465c800..a00ad764c71f67e0e4e6e6ee81f821cb890f7d05 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.197 2006/01/25 20:29:23 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.198 2006/01/26 02:35:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2024,8 +2024,6 @@ match_special_index_operator(Expr *clause, Oid opclass,
 
                case OID_INET_SUB_OP:
                case OID_INET_SUBEQ_OP:
-               case OID_CIDR_SUB_OP:
-               case OID_CIDR_SUBEQ_OP:
                        isIndexable = true;
                        break;
        }
@@ -2087,12 +2085,8 @@ match_special_index_operator(Expr *clause, Oid opclass,
 
                case OID_INET_SUB_OP:
                case OID_INET_SUBEQ_OP:
-                       isIndexable = (opclass == INET_BTREE_OPS_OID);
-                       break;
-
-               case OID_CIDR_SUB_OP:
-               case OID_CIDR_SUBEQ_OP:
-                       isIndexable = (opclass == CIDR_BTREE_OPS_OID);
+                       isIndexable = (opclass == INET_BTREE_OPS_OID ||
+                                                  opclass == CIDR_BTREE_OPS_OID);
                        break;
        }
 
@@ -2317,8 +2311,6 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
 
                case OID_INET_SUB_OP:
                case OID_INET_SUBEQ_OP:
-               case OID_CIDR_SUB_OP:
-               case OID_CIDR_SUBEQ_OP:
                        result = network_prefix_quals(leftop, expr_op, opclass,
                                                                                  patt->constvalue);
                        break;
@@ -2681,14 +2673,6 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
                        datatype = INETOID;
                        is_eq = true;
                        break;
-               case OID_CIDR_SUB_OP:
-                       datatype = CIDROID;
-                       is_eq = false;
-                       break;
-               case OID_CIDR_SUBEQ_OP:
-                       datatype = CIDROID;
-                       is_eq = true;
-                       break;
                default:
                        elog(ERROR, "unexpected operator: %u", expr_op);
                        return NIL;
index 567a7cc2ee5c03a1accbd96595bd2edace02d002..c827dab69670236a848c199d0dd8d3979f070c3e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     PostgreSQL type definitions for the INET and CIDR types.
  *
- *     $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.60 2006/01/23 21:49:39 momjian Exp $
+ *     $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.61 2006/01/26 02:35:49 tgl Exp $
  *
  *     Jon Postel RIP 16 Oct 1998
  */
@@ -22,7 +22,7 @@
 #include "utils/inet.h"
 
 
-static Datum text_network(text *src, bool is_cidr);
+static inet *text_network(text *src, bool is_cidr);
 static int32 network_cmp_internal(inet *a1, inet *a2);
 static int     bitncmp(void *l, void *r, int n);
 static bool addressOK(unsigned char *a, int bits, int family);
@@ -38,9 +38,6 @@ static int    ip_addrsize(inet *inetptr);
 #define ip_bits(inetptr) \
        (((inet_struct *)VARDATA(inetptr))->bits)
 
-#define ip_is_cidr(inetptr) \
-       (((inet_struct *)VARDATA(inetptr))->is_cidr)
-
 #define ip_addr(inetptr) \
        (((inet_struct *)VARDATA(inetptr))->ipaddr)
 
@@ -64,7 +61,9 @@ ip_addrsize(inet *inetptr)
        }
 }
 
-/* Common input routine */
+/*
+ * Common INET/CIDR input routine
+ */
 static inet *
 network_in(char *src, bool is_cidr)
 {
@@ -109,37 +108,33 @@ network_in(char *src, bool is_cidr)
                + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
                + ip_addrsize(dst);
        ip_bits(dst) = bits;
-       ip_is_cidr(dst) = is_cidr;
 
        return dst;
 }
 
-/* INET address reader.  */
 Datum
 inet_in(PG_FUNCTION_ARGS)
 {
        char       *src = PG_GETARG_CSTRING(0);
 
-       PG_RETURN_INET_P(network_in(src, 0));
+       PG_RETURN_INET_P(network_in(src, false));
 }
 
-/* CIDR address reader.  */
 Datum
 cidr_in(PG_FUNCTION_ARGS)
 {
        char       *src = PG_GETARG_CSTRING(0);
 
-       PG_RETURN_INET_P(network_in(src, 1));
+       PG_RETURN_INET_P(network_in(src, true));
 }
 
 
 /*
- *     INET address output function.
+ * Common INET/CIDR output routine
  */
-Datum
-inet_out(PG_FUNCTION_ARGS)
+static char *
+network_out(inet *src, bool is_cidr)
 {
-       inet       *src = PG_GETARG_INET_P(0);
        char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
        char       *dst;
        int                     len;
@@ -152,34 +147,45 @@ inet_out(PG_FUNCTION_ARGS)
                                 errmsg("could not format inet value: %m")));
 
        /* For CIDR, add /n if not present */
-       if (ip_is_cidr(src) && strchr(tmp, '/') == NULL)
+       if (is_cidr && strchr(tmp, '/') == NULL)
        {
                len = strlen(tmp);
                snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
        }
 
-       PG_RETURN_CSTRING(pstrdup(tmp));
+       return pstrdup(tmp);
 }
 
+Datum
+inet_out(PG_FUNCTION_ARGS)
+{
+       inet       *src = PG_GETARG_INET_P(0);
+
+       PG_RETURN_CSTRING(network_out(src, false));
+}
 
-/* share code with INET case */
 Datum
 cidr_out(PG_FUNCTION_ARGS)
 {
-       return inet_out(fcinfo);
+       inet       *src = PG_GETARG_INET_P(0);
+
+       PG_RETURN_CSTRING(network_out(src, true));
 }
 
 
 /*
- *             inet_recv                       - converts external binary format to inet
+ *             network_recv            - converts external binary format to inet
  *
  * The external representation is (one byte apiece for)
  * family, bits, is_cidr, address length, address in network byte order.
+ *
+ * Presence of is_cidr is largely for historical reasons, though it might
+ * allow some code-sharing on the client side.  We send it correctly on
+ * output, but ignore the value on input.
  */
-Datum
-inet_recv(PG_FUNCTION_ARGS)
+static inet *
+network_recv(StringInfo buf, bool is_cidr)
 {
-       StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
        inet       *addr;
        char       *addrptr;
        int                     bits;
@@ -194,23 +200,25 @@ inet_recv(PG_FUNCTION_ARGS)
                ip_family(addr) != PGSQL_AF_INET6)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
-                          errmsg("invalid address family in external \"inet\" value")));
+                                /* translator: %s is inet or cidr */
+                                errmsg("invalid address family in external \"%s\" value",
+                                               is_cidr ? "cidr" : "inet")));
        bits = pq_getmsgbyte(buf);
        if (bits < 0 || bits > ip_maxbits(addr))
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
-                                errmsg("invalid bits in external \"inet\" value")));
+                                /* translator: %s is inet or cidr */
+                                errmsg("invalid bits in external \"%s\" value",
+                                               is_cidr ? "cidr" : "inet")));
        ip_bits(addr) = bits;
-       ip_is_cidr(addr) = pq_getmsgbyte(buf);
-       if (ip_is_cidr(addr) != false && ip_is_cidr(addr) != true)
-               ereport(ERROR,
-                               (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
-                                errmsg("invalid type in external \"inet\" value")));
+       i = pq_getmsgbyte(buf);         /* ignore is_cidr */
        nb = pq_getmsgbyte(buf);
        if (nb != ip_addrsize(addr))
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
-                                errmsg("invalid length in external \"inet\" value")));
+                                /* translator: %s is inet or cidr */
+                                errmsg("invalid length in external \"%s\" value",
+                                               is_cidr ? "cidr" : "inet")));
        VARATT_SIZEP(addr) = VARHDRSZ
                + ((char *) ip_addr(addr) - (char *) VARDATA(addr))
                + ip_addrsize(addr);
@@ -222,7 +230,7 @@ inet_recv(PG_FUNCTION_ARGS)
        /*
         * Error check: CIDR values must not have any bits set beyond the masklen.
         */
-       if (ip_is_cidr(addr))
+       if (is_cidr)
        {
                if (!addressOK(ip_addr(addr), bits, ip_family(addr)))
                        ereport(ERROR,
@@ -231,23 +239,32 @@ inet_recv(PG_FUNCTION_ARGS)
                                         errdetail("Value has bits set to right of mask.")));
        }
 
-       PG_RETURN_INET_P(addr);
+       return addr;
+}
+
+Datum
+inet_recv(PG_FUNCTION_ARGS)
+{
+       StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+
+       PG_RETURN_INET_P(network_recv(buf, false));
 }
 
-/* share code with INET case */
 Datum
 cidr_recv(PG_FUNCTION_ARGS)
 {
-       return inet_recv(fcinfo);
+       StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+
+       PG_RETURN_INET_P(network_recv(buf, true));
 }
 
+
 /*
- *             inet_send                       - converts inet to binary format
+ *             network_send            - converts inet to binary format
  */
-Datum
-inet_send(PG_FUNCTION_ARGS)
+static bytea *
+network_send(inet *addr, bool is_cidr)
 {
-       inet       *addr = PG_GETARG_INET_P(0);
        StringInfoData buf;
        char       *addrptr;
        int                     nb,
@@ -256,7 +273,7 @@ inet_send(PG_FUNCTION_ARGS)
        pq_begintypsend(&buf);
        pq_sendbyte(&buf, ip_family(addr));
        pq_sendbyte(&buf, ip_bits(addr));
-       pq_sendbyte(&buf, ip_is_cidr(addr));
+       pq_sendbyte(&buf, is_cidr);
        nb = ip_addrsize(addr);
        if (nb < 0)
                nb = 0;
@@ -264,41 +281,93 @@ inet_send(PG_FUNCTION_ARGS)
        addrptr = (char *) ip_addr(addr);
        for (i = 0; i < nb; i++)
                pq_sendbyte(&buf, addrptr[i]);
-       PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+       return pq_endtypsend(&buf);
+}
+
+Datum
+inet_send(PG_FUNCTION_ARGS)
+{
+       inet       *addr = PG_GETARG_INET_P(0);
+
+       PG_RETURN_BYTEA_P(network_send(addr, false));
 }
 
-/* share code with INET case */
 Datum
 cidr_send(PG_FUNCTION_ARGS)
 {
-       return inet_send(fcinfo);
+       inet       *addr = PG_GETARG_INET_P(0);
+
+       PG_RETURN_BYTEA_P(network_send(addr, true));
 }
 
 
-static Datum
+static inet *
 text_network(text *src, bool is_cidr)
 {
        int                     len = VARSIZE(src) - VARHDRSZ;
-
        char       *str = palloc(len + 1);
 
        memcpy(str, VARDATA(src), len);
-       *(str + len) = '\0';
+       str[len] = '\0';
 
-       PG_RETURN_INET_P(network_in(str, is_cidr));
+       return network_in(str, is_cidr);
 }
 
+Datum
+text_inet(PG_FUNCTION_ARGS)
+{
+       text       *src = PG_GETARG_TEXT_P(0);
+
+       PG_RETURN_INET_P(text_network(src, false));
+}
 
 Datum
 text_cidr(PG_FUNCTION_ARGS)
 {
-       return text_network(PG_GETARG_TEXT_P(0), 1);
+       text       *src = PG_GETARG_TEXT_P(0);
+
+       PG_RETURN_INET_P(text_network(src, true));
 }
 
+
 Datum
-text_inet(PG_FUNCTION_ARGS)
+inet_to_cidr(PG_FUNCTION_ARGS)
 {
-       return text_network(PG_GETARG_TEXT_P(0), 0);
+       inet       *src = PG_GETARG_INET_P(0);
+       inet       *dst;
+       int                     bits;
+       int                     byte;
+       int                     nbits;
+       int                     maxbytes;
+
+       bits = ip_bits(src);
+
+       /* safety check */
+       if ((bits < 0) || (bits > ip_maxbits(src)))
+               elog(ERROR, "invalid inet bit length: %d", bits);
+
+       /* clone the original data */
+       dst = (inet *) palloc(VARSIZE(src));
+       memcpy(dst, src, VARSIZE(src));
+
+       /* zero out any bits to the right of the netmask */
+       byte = bits / 8;
+       nbits = bits % 8;
+       /* clear the first byte, this might be a partial byte */
+       if (nbits != 0)
+       {
+               ip_addr(dst)[byte] &= ~(0xFF >> nbits);
+               byte++;
+       }
+       /* clear remaining bytes */
+       maxbytes = ip_addrsize(dst);
+       while (byte < maxbytes)
+       {
+               ip_addr(dst)[byte] = 0;
+               byte++;
+       }
+
+       PG_RETURN_INET_P(dst);
 }
 
 Datum
@@ -325,6 +394,50 @@ inet_set_masklen(PG_FUNCTION_ARGS)
        PG_RETURN_INET_P(dst);
 }
 
+Datum
+cidr_set_masklen(PG_FUNCTION_ARGS)
+{
+       inet       *src = PG_GETARG_INET_P(0);
+       int                     bits = PG_GETARG_INT32(1);
+       inet       *dst;
+       int                     byte;
+       int                     nbits;
+       int                     maxbytes;
+
+       if (bits == -1)
+               bits = ip_maxbits(src);
+
+       if ((bits < 0) || (bits > ip_maxbits(src)))
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("invalid mask length: %d", bits)));
+
+       /* clone the original data */
+       dst = (inet *) palloc(VARSIZE(src));
+       memcpy(dst, src, VARSIZE(src));
+
+       ip_bits(dst) = bits;
+
+       /* zero out any bits to the right of the new netmask */
+       byte = bits / 8;
+       nbits = bits % 8;
+       /* clear the first byte, this might be a partial byte */
+       if (nbits != 0)
+       {
+               ip_addr(dst)[byte] &= ~(0xFF >> nbits);
+               byte++;
+       }
+       /* clear remaining bytes */
+       maxbytes = ip_addrsize(dst);
+       while (byte < maxbytes)
+       {
+               ip_addr(dst)[byte] = 0;
+               byte++;
+       }
+
+       PG_RETURN_INET_P(dst);
+}
+
 /*
  *     Basic comparison function for sorting and inet/cidr comparisons.
  *
@@ -424,23 +537,15 @@ network_ne(PG_FUNCTION_ARGS)
 
 /*
  * Support function for hash indexes on inet/cidr.
- *
- * Since network_cmp considers only ip_family, ip_bits, and ip_addr, only
- * these fields may be used in the hash; in particular don't use is_cidr.
  */
 Datum
 hashinet(PG_FUNCTION_ARGS)
 {
        inet       *addr = PG_GETARG_INET_P(0);
        int                     addrsize = ip_addrsize(addr);
-       unsigned char key[sizeof(inet_struct)];
-
-       Assert(addrsize + 2 <= sizeof(key));
-       key[0] = ip_family(addr);
-       key[1] = ip_bits(addr);
-       memcpy(key + 2, ip_addr(addr), addrsize);
 
-       return hash_any(key, addrsize + 2);
+       /* XXX this assumes there are no pad bytes in the data structure */
+       return hash_any(VARDATA(addr), addrsize + 2);
 }
 
 /*
@@ -567,7 +672,7 @@ network_show(PG_FUNCTION_ARGS)
 }
 
 Datum
-network_abbrev(PG_FUNCTION_ARGS)
+inet_abbrev(PG_FUNCTION_ARGS)
 {
        inet       *ip = PG_GETARG_INET_P(0);
        text       *ret;
@@ -575,12 +680,8 @@ network_abbrev(PG_FUNCTION_ARGS)
        int                     len;
        char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
 
-       if (ip_is_cidr(ip))
-               dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
-                                                        ip_bits(ip), tmp, sizeof(tmp));
-       else
-               dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
-                                                       ip_bits(ip), tmp, sizeof(tmp));
+       dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
+                                               ip_bits(ip), tmp, sizeof(tmp));
 
        if (dst == NULL)
                ereport(ERROR,
@@ -595,6 +696,31 @@ network_abbrev(PG_FUNCTION_ARGS)
        PG_RETURN_TEXT_P(ret);
 }
 
+Datum
+cidr_abbrev(PG_FUNCTION_ARGS)
+{
+       inet       *ip = PG_GETARG_INET_P(0);
+       text       *ret;
+       char       *dst;
+       int                     len;
+       char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
+
+       dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
+                                                ip_bits(ip), tmp, sizeof(tmp));
+
+       if (dst == NULL)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
+                                errmsg("could not format cidr value: %m")));
+
+       /* Return string as a text datum */
+       len = strlen(tmp);
+       ret = (text *) palloc(len + VARHDRSZ);
+       VARATT_SIZEP(ret) = len + VARHDRSZ;
+       memcpy(VARDATA(ret), tmp, len);
+       PG_RETURN_TEXT_P(ret);
+}
+
 Datum
 network_masklen(PG_FUNCTION_ARGS)
 {
@@ -666,7 +792,6 @@ network_broadcast(PG_FUNCTION_ARGS)
 
        ip_family(dst) = ip_family(ip);
        ip_bits(dst) = ip_bits(ip);
-       ip_is_cidr(dst) = false;
        VARATT_SIZEP(dst) = VARHDRSZ
                + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
                + ip_addrsize(dst);
@@ -712,7 +837,6 @@ network_network(PG_FUNCTION_ARGS)
 
        ip_family(dst) = ip_family(ip);
        ip_bits(dst) = ip_bits(ip);
-       ip_is_cidr(dst) = true;
        VARATT_SIZEP(dst) = VARHDRSZ
                + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
                + ip_addrsize(dst);
@@ -756,7 +880,6 @@ network_netmask(PG_FUNCTION_ARGS)
 
        ip_family(dst) = ip_family(ip);
        ip_bits(dst) = ip_maxbits(ip);
-       ip_is_cidr(dst) = false;
        VARATT_SIZEP(dst) = VARHDRSZ
                + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
                + ip_addrsize(dst);
@@ -806,7 +929,6 @@ network_hostmask(PG_FUNCTION_ARGS)
 
        ip_family(dst) = ip_family(ip);
        ip_bits(dst) = ip_maxbits(ip);
-       ip_is_cidr(dst) = false;
        VARATT_SIZEP(dst) = VARHDRSZ
                + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
                + ip_addrsize(dst);
@@ -818,11 +940,6 @@ network_hostmask(PG_FUNCTION_ARGS)
  * Convert a value of a network datatype to an approximate scalar value.
  * This is used for estimating selectivities of inequality operators
  * involving network types.
- *
- * Currently, inet/cidr values are simply converted to the IPv4 address;
- * this will need more thought when IPv6 is supported too.     MAC addresses
- * are converted to their numeric equivalent as well (OK since we have a
- * double to play in).
  */
 double
 convert_network_to_scalar(Datum value, Oid typid)
@@ -838,7 +955,7 @@ convert_network_to_scalar(Datum value, Oid typid)
                                int                     i;
 
                                /*
-                                * Note that we don't use the full address here.
+                                * Note that we don't use the full address for IPv6.
                                 */
                                if (ip_family(ip) == PGSQL_AF_INET)
                                        len = 4;
@@ -1020,7 +1137,7 @@ inet_client_addr(PG_FUNCTION_ARGS)
        if (ret)
                PG_RETURN_NULL();
 
-       PG_RETURN_INET_P(network_in(remote_host, 0));
+       PG_RETURN_INET_P(network_in(remote_host, false));
 }
 
 
@@ -1094,7 +1211,7 @@ inet_server_addr(PG_FUNCTION_ARGS)
        if (ret)
                PG_RETURN_NULL();
 
-       PG_RETURN_INET_P(network_in(local_host, 0));
+       PG_RETURN_INET_P(network_in(local_host, false));
 }
 
 
index 2742b700275a5fba788f8e10958f7bf216c916c3..7887bdb8aa1e57ed5de72e0e11f2ead031afd91c 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.312 2006/01/18 06:49:27 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.313 2006/01/26 02:35:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200601181
+#define CATALOG_VERSION_NO     200601251
 
 #endif
index 55b289212d9e6644b6cdc6a9e2593caef1678a7a..d4932ed89c4b4f314eac3c9f2bbcbafb441f0ccc 100644 (file)
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.67 2005/11/07 17:36:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.68 2006/01/26 02:35:49 tgl Exp $
  *
  * NOTES
  *      the genbki.sh script reads this file and generates .bki
@@ -388,11 +388,11 @@ DATA(insert (     1974    0 5 f 1205 ));
  *     btree cidr
  */
 
-DATA(insert (   432    0 1 f  822 ));
-DATA(insert (   432    0 2 f  823 ));
-DATA(insert (   432    0 3 f  820 ));
-DATA(insert (   432    0 4 f  825 ));
-DATA(insert (   432    0 5 f  824 ));
+DATA(insert (   432    0 1 f 1203 ));
+DATA(insert (   432    0 2 f 1204 ));
+DATA(insert (   432    0 3 f 1201 ));
+DATA(insert (   432    0 4 f 1206 ));
+DATA(insert (   432    0 5 f 1205 ));
 
 /*
  *     btree numeric
@@ -523,7 +523,7 @@ DATA(insert (        427    0 1 f 1054 ));
 /* char_ops */
 DATA(insert (   431    0 1 f   92 ));
 /* cidr_ops */
-DATA(insert (   433    0 1 f  820 ));
+DATA(insert (   433    0 1 f 1201 ));
 /* date_ops */
 DATA(insert (   435    0 1 f 1093 ));
 /* float4_ops */
index d0dfbecd628aa4a38a2ed4674294b5a18e066c24..db52b892fd44bb37d37cc98229de3f20b87c112b 100644 (file)
@@ -10,7 +10,7 @@
  *
  * Copyright (c) 2002-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.24 2005/10/21 15:45:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.25 2006/01/26 02:35:49 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -249,7 +249,7 @@ DATA(insert (  718  604 1544 e ));
  * INET category
  */
 DATA(insert (  650     869    0 i ));
-DATA(insert (  869     650    0 i ));
+DATA(insert (  869     650 1715 a ));
 
 /*
  * BitString category
index 678ed306f2094727ee152d373f6660690bc85330..9b426f6c5951b008e15b32b9e228ed231968f3ca 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.137 2005/10/15 02:49:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.138 2006/01/26 02:35:49 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -637,7 +637,7 @@ DATA(insert OID = 1223 (  "<="         PGNSP PGUID b f 829 829       16 1225 1224    0        0
 DATA(insert OID = 1224 (  ">"     PGNSP PGUID b f 829 829       16 1222 1223    0        0   0   0 macaddr_gt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 1225 (  ">="    PGNSP PGUID b f 829 829       16 1223 1222    0        0   0   0 macaddr_ge scalargtsel scalargtjoinsel ));
 
-/* INET type */
+/* INET type (these also support CIDR via implicit cast) */
 DATA(insert OID = 1201 (  "="     PGNSP PGUID b t 869 869       16 1201 1202 1203 1203 1203 1205 network_eq eqsel eqjoinsel ));
 DATA(insert OID = 1202 (  "<>"    PGNSP PGUID b f 869 869       16 1202 1201    0        0   0   0 network_ne neqsel neqjoinsel ));
 DATA(insert OID = 1203 (  "<"     PGNSP PGUID b f 869 869       16 1205 1206    0        0   0   0 network_lt scalarltsel scalarltjoinsel ));
@@ -653,22 +653,6 @@ DATA(insert OID = 933  (  ">>"        PGNSP PGUID b f 869 869       16 931         0        0        0   0
 DATA(insert OID = 934  (  ">>="    PGNSP PGUID b f 869 869      16 932         0        0        0   0   0 network_supeq - - ));
 #define OID_INET_SUPEQ_OP                              934
 
-/* CIDR type */
-DATA(insert OID = 820 (  "="      PGNSP PGUID b t 650 650       16 820 821 822 822 822 824 network_eq eqsel eqjoinsel ));
-DATA(insert OID = 821 (  "<>"     PGNSP PGUID b f 650 650       16 821 820   0   0   0   0 network_ne neqsel neqjoinsel ));
-DATA(insert OID = 822 (  "<"      PGNSP PGUID b f 650 650       16 824 825   0   0   0   0 network_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 823 (  "<="     PGNSP PGUID b f 650 650       16 825 824   0   0   0   0 network_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 824 (  ">"      PGNSP PGUID b f 650 650       16 822 823   0   0   0   0 network_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 825 (  ">="     PGNSP PGUID b f 650 650       16 823 822   0   0   0   0 network_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 826 (  "<<"     PGNSP PGUID b f 650 650       16 828   0   0   0   0   0 network_sub - - ));
-#define OID_CIDR_SUB_OP                826
-DATA(insert OID = 827 (  "<<="    PGNSP PGUID b f 650 650       16 1004  0   0   0   0   0 network_subeq - - ));
-#define OID_CIDR_SUBEQ_OP      827
-DATA(insert OID = 828 (  ">>"     PGNSP PGUID b f 650 650       16 826   0   0   0   0   0 network_sup - - ));
-#define OID_CIDR_SUP_OP                828
-DATA(insert OID = 1004 ( ">>="    PGNSP PGUID b f 650 650       16 827   0   0   0   0   0 network_supeq - - ));
-#define OID_CIDR_SUPEQ_OP      1004
-
 /* case-insensitive LIKE hacks */
 DATA(insert OID = 1625 (  "~~*"   PGNSP PGUID b f  19  25      16 0 1626 0 0 0 0 nameiclike iclikesel iclikejoinsel ));
 #define OID_NAME_ICLIKE_OP             1625
index 5c54d831cdb5e89dc843e42bce0dceb870ec097d..a79a58c2e999a77b71ac079279355acd5e361708 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.392 2006/01/18 06:49:28 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.393 2006/01/26 02:35:49 tgl Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -2391,10 +2391,16 @@ DATA(insert OID = 930 (  network_supeq          PGNSP PGUID 12 f f t f i 2 16 "869 869"
 DESCR("is-supernet-or-equal");
 
 /* inet/cidr functions */
-DATA(insert OID = 605 (  abbrev                                PGNSP PGUID 12 f f t f i 1 25 "869" _null_ _null_ _null_        network_abbrev - _null_ ));
-DESCR("abbreviated display of inet/cidr value");
+DATA(insert OID = 598 (  abbrev                                PGNSP PGUID 12 f f t f i 1 25 "869" _null_ _null_ _null_        inet_abbrev - _null_ ));
+DESCR("abbreviated display of inet value");
+DATA(insert OID = 599 (  abbrev                                PGNSP PGUID 12 f f t f i 1 25 "650" _null_ _null_ _null_        cidr_abbrev - _null_ ));
+DESCR("abbreviated display of cidr value");
+DATA(insert OID = 605 (  set_masklen           PGNSP PGUID 12 f f t f i 2 869 "869 23" _null_ _null_ _null_    inet_set_masklen - _null_ ));
+DESCR("change netmask of inet");
+DATA(insert OID = 635 (  set_masklen           PGNSP PGUID 12 f f t f i 2 650 "650 23" _null_ _null_ _null_    cidr_set_masklen - _null_ ));
+DESCR("change netmask of cidr");
 DATA(insert OID = 711 (  family                                PGNSP PGUID 12 f f t f i 1 23 "869" _null_ _null_ _null_        network_family - _null_ ));
-DESCR("return address family (4 for IPv4, 6 for IPv6)");
+DESCR("address family (4 for IPv4, 6 for IPv6)");
 DATA(insert OID = 683 (  network                       PGNSP PGUID 12 f f t f i 1 650 "869" _null_ _null_ _null_ network_network - _null_ ));
 DESCR("network part of address");
 DATA(insert OID = 696 (  netmask                       PGNSP PGUID 12 f f t f i 1 869 "869" _null_ _null_ _null_ network_netmask - _null_ ));
@@ -2413,8 +2419,8 @@ DATA(insert OID = 1713 (  inet                            PGNSP PGUID 12 f f t f i 1 869 "25" _null_ _nu
 DESCR("text to inet");
 DATA(insert OID = 1714 (  cidr                         PGNSP PGUID 12 f f t f i 1 650 "25" _null_ _null_ _null_        text_cidr - _null_ ));
 DESCR("text to cidr");
-DATA(insert OID = 1715 (  set_masklen          PGNSP PGUID 12 f f t f i 2 869 "869 23" _null_ _null_ _null_    inet_set_masklen - _null_ ));
-DESCR("change the netmask of an inet");
+DATA(insert OID = 1715 (  cidr                         PGNSP PGUID 12 f f t f i 1 650 "869" _null_ _null_ _null_       inet_to_cidr - _null_ ));
+DESCR("coerce inet to cidr");
 
 DATA(insert OID = 2196 (  inet_client_addr             PGNSP PGUID 12 f f f f s 0 869 "" _null_ _null_ _null_  inet_client_addr - _null_ ));
 DESCR("INET address of the client");
index e8ad4bd0e21b05404429dc40f8af5bdee9b6e37a..527d5ce8e88d7c98e08b0a671f34a9677530fb59 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.271 2006/01/18 06:49:29 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.272 2006/01/26 02:35:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -720,11 +720,14 @@ extern Datum network_family(PG_FUNCTION_ARGS);
 extern Datum network_broadcast(PG_FUNCTION_ARGS);
 extern Datum network_host(PG_FUNCTION_ARGS);
 extern Datum network_show(PG_FUNCTION_ARGS);
-extern Datum network_abbrev(PG_FUNCTION_ARGS);
+extern Datum inet_abbrev(PG_FUNCTION_ARGS);
+extern Datum cidr_abbrev(PG_FUNCTION_ARGS);
 extern double convert_network_to_scalar(Datum value, Oid typid);
 extern Datum text_cidr(PG_FUNCTION_ARGS);
 extern Datum text_inet(PG_FUNCTION_ARGS);
+extern Datum inet_to_cidr(PG_FUNCTION_ARGS);
 extern Datum inet_set_masklen(PG_FUNCTION_ARGS);
+extern Datum cidr_set_masklen(PG_FUNCTION_ARGS);
 extern Datum network_scan_first(Datum in);
 extern Datum network_scan_last(Datum in);
 extern Datum inet_client_addr(PG_FUNCTION_ARGS);
index 03b8ee4b7edf6055db0e9c199fe2667a0964d762..ad6215d772681cf9436d8eebc58b384b09819a0e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/inet.h,v 1.21 2006/01/23 21:45:47 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/inet.h,v 1.22 2006/01/26 02:35:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,6 @@ typedef struct
 {
        unsigned char family;           /* PGSQL_AF_INET or PGSQL_AF_INET6 */
        unsigned char bits;                     /* number of bits in netmask */
-       bool is_cidr;                           /* is cidr? */
        unsigned char ipaddr[16];       /* up to 128 bits of address */
 } inet_struct;
 
index aad7a10ed0a0ff1ddd3a8e946a19d248b8f24fcf..f367d0a5526ac775906f21054249b1f8aa5feae7 100644 (file)
@@ -274,6 +274,8 @@ WHERE c.castfunc = p.oid AND
 -- also binary compatible.  This is legal, but usually not intended.
 -- As of 7.4, this finds the casts from text and varchar to bpchar, because
 -- those are binary-compatible while the reverse way goes through rtrim().
+-- As of 8.2, this finds the cast from cidr to inet, because that is a
+-- trivial binary coercion while the other way goes through inet_to_cidr().
 SELECT *
 FROM pg_cast c
 WHERE c.castfunc = 0 AND
@@ -285,7 +287,8 @@ WHERE c.castfunc = 0 AND
 ------------+------------+----------+-------------
          25 |       1042 |        0 | i
        1043 |       1042 |        0 | i
-(2 rows)
+        650 |        869 |        0 | i
+(3 rows)
 
 -- **************** pg_operator ****************
 -- Look for illegal values in pg_operator fields.
index ea5bc5b4366f2cabe0b11e6d0a3480032100ac8d..0528e3657c3cbe839463a0bd10351f1eb6bc54be 100644 (file)
@@ -223,6 +223,9 @@ WHERE c.castfunc = p.oid AND
 -- As of 7.4, this finds the casts from text and varchar to bpchar, because
 -- those are binary-compatible while the reverse way goes through rtrim().
 
+-- As of 8.2, this finds the cast from cidr to inet, because that is a
+-- trivial binary coercion while the other way goes through inet_to_cidr().
+
 SELECT *
 FROM pg_cast c
 WHERE c.castfunc = 0 AND