Thread: contrib/xinetops for 8.1 "patch"

contrib/xinetops for 8.1 "patch"

From
"Stephen R. van den Berg"
Date:
I've been meaning to send it in for a while now, IMHO it could be
made part of the main distribution as well, but contrib is fine
if not everyone likes it.

I included the source in patch-format, since I didn't feel comfortable
attaching a tar.gz file on this list.
Below is an excerpt from the included README:
-------------------------------- cut here ---------------------------------
inet extended operations
~~~~~~~~~~~~~~~~~~~~~~~~

This directory contains definitions for extended operators on the
inet data type.

Operators available are:

   ~ & | + -

It supports the "natural" arithmetic with IP addresses and integers.
It is useful for applications which have to hand out and administer
ranges of IP-addresses (like a Radius or DHCP server).

Copyright (c) 2003-2006, Stephen R. van den Berg, The Netherlands.
             <srb@cuci.nl>

This module is distributed under the same BSD license as PostgreSQL.
-------------------------------- cut here ---------------------------------

diff -ur xinetops.old/Makefile xinetops/Makefile
--- xinetops.old/Makefile    2005-11-13 12:36:39.000000000 +0100
+++ xinetops/Makefile    2005-11-13 12:45:04.000000000 +0100
@@ -0,0 +1,11 @@
+# $Id: Makefile 523 2005-11-13 11:29:44Z srb $
+
+subdir = contrib/xinetops
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+MODULES = xinetops
+DATA_built = xinetops.sql
+DOCS = README.xinetops
+
+include $(top_srcdir)/contrib/contrib-global.mk
diff -ur xinetops.old/README.xinetops xinetops/README.xinetops
--- xinetops.old/README.xinetops    2005-11-13 12:36:39.000000000 +0100
+++ xinetops/README.xinetops    2005-11-13 12:45:04.000000000 +0100
@@ -0,0 +1,19 @@
+
+inet extended operations
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+This directory contains definitions for extended operators on the
+inet data type.
+
+Operators available are:
+
+   ~ & | + -
+
+It supports the "natural" arithmetic with IP addresses and integers.
+It is useful for applications which have to hand out and administer
+ranges of IP-addresses (like a Radius or DHCP server).
+
+Copyright (c) 2003-2006, Stephen R. van den Berg, The Netherlands.
+             <srb@cuci.nl>
+
+This module is distributed under the same BSD license as PostgreSQL.
diff -ur xinetops.old/xinetops.c xinetops/xinetops.c
--- xinetops.old/xinetops.c    2005-11-13 12:36:39.000000000 +0100
+++ xinetops/xinetops.c    2005-11-13 12:45:04.000000000 +0100
@@ -0,0 +1,254 @@
+/*
+ *    PostgreSQL type definitions for extended inet operations.
+ *    Copyright (c) 2003-2006, S.R. van den Berg, The Netherlands
+ *                 <srb@cuci.nl>
+ *
+ *      This module is distributed under the same BSD license as PostgreSQL.
+ *
+ *    $Id: xinetops.c 524 2005-11-13 11:44:43Z srb $
+ */
+
+#include "postgres.h"
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "catalog/pg_type.h"
+#include "utils/builtins.h"
+#include "utils/inet.h"
+
+#define ip_family(inetptr) \
+        (((inet_struct *)VARDATA(inetptr))->family)
+
+#define ip_bits(inetptr) \
+        (((inet_struct *)VARDATA(inetptr))->bits)
+
+#define ip_type(inetptr) \
+        (((inet_struct *)VARDATA(inetptr))->type)
+
+#define ip_addr(inetptr) \
+        (((inet_struct *)VARDATA(inetptr))->ipaddr)
+
+static int
+ip_addrsize(inet *inetptr)
+{
+        switch (ip_family(inetptr))
+        {
+                case PGSQL_AF_INET:
+                        return 4;
+                case PGSQL_AF_INET6:
+                        return 16;
+                default:
+                        return -1;
+        }
+}
+
+
+PG_FUNCTION_INFO_V1(inet_not);
+
+Datum
+inet_not(PG_FUNCTION_ARGS)
+{
+    inet       *ip = PG_GETARG_INET_P(0);
+    inet       *dst;
+
+    dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
+    /* make sure any unused bits are zeroed */
+    MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
+
+        {
+           int nb = ip_addrsize(ip);
+           unsigned char*pip = ip_addr(ip);
+           unsigned char*pdst = ip_addr(dst);
+
+           while (nb-->0)
+           {
+            pdst[nb] = pip[nb];
+           }
+        }
+    ip_bits(dst) = ip_bits(ip);
+
+    ip_family(dst) = ip_family(ip);
+    ip_type(dst) = 0;
+    VARATT_SIZEP(dst) = VARHDRSZ
+        + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+        + ip_addrsize(dst);
+
+    PG_RETURN_INET_P(dst);
+}
+
+PG_FUNCTION_INFO_V1(inet_or);
+
+Datum
+inet_or(PG_FUNCTION_ARGS)
+{
+    inet       *ip = PG_GETARG_INET_P(0);
+    inet       *ip2 = PG_GETARG_INET_P(1);
+    inet       *dst;
+
+    dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
+    /* make sure any unused bits are zeroed */
+    MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
+
+    if (ip_family(ip) != ip_family(ip2))
+        elog(ERROR, "mismatch in address family (%d)!=(%d)",
+                ip_family(ip), ip_family(ip2));
+    else
+        {
+           int nb = ip_addrsize(ip);
+           unsigned char*pip = ip_addr(ip);
+           unsigned char*pip2 = ip_addr(ip2);
+           unsigned char*pdst = ip_addr(dst);
+
+           while (nb-->0)
+           {
+            pdst[nb] = pip[nb]|pip2[nb];
+           }
+        }
+    ip_bits(dst) = ip_bits(ip);
+    if (ip_bits(dst)<ip_bits(ip2))
+        ip_bits(dst) = ip_bits(ip2);
+
+    ip_family(dst) = ip_family(ip);
+    ip_type(dst) = 0;
+    VARATT_SIZEP(dst) = VARHDRSZ
+        + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+        + ip_addrsize(dst);
+
+    PG_RETURN_INET_P(dst);
+}
+
+PG_FUNCTION_INFO_V1(inet_and);
+
+Datum
+inet_and(PG_FUNCTION_ARGS)
+{
+    inet       *ip = PG_GETARG_INET_P(0);
+    inet       *ip2 = PG_GETARG_INET_P(1);
+    inet       *dst;
+
+    dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
+    /* make sure any unused bits are zeroed */
+    MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
+
+    if (ip_family(ip) != ip_family(ip2))
+        elog(ERROR, "mismatch in address family (%d)!=(%d)",
+                ip_family(ip), ip_family(ip2));
+    else
+        {
+           int nb = ip_addrsize(ip);
+           unsigned char*pip = ip_addr(ip);
+           unsigned char*pip2 = ip_addr(ip2);
+           unsigned char*pdst = ip_addr(dst);
+
+           while (nb-->0)
+           {
+            pdst[nb] = pip[nb]&pip2[nb];
+           }
+        }
+    ip_bits(dst) = ip_bits(ip);
+    if (ip_bits(dst)<ip_bits(ip2))
+        ip_bits(dst) = ip_bits(ip2);
+
+    ip_family(dst) = ip_family(ip);
+    ip_type(dst) = 0;
+    VARATT_SIZEP(dst) = VARHDRSZ
+        + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+        + ip_addrsize(dst);
+
+    PG_RETURN_INET_P(dst);
+}
+
+PG_FUNCTION_INFO_V1(inet_min);
+
+Datum
+inet_min(PG_FUNCTION_ARGS)
+{
+    inet       *ip = PG_GETARG_INET_P(0);
+    inet       *ip2 = PG_GETARG_INET_P(1);
+    int       res = 0;
+
+    if (ip_family(ip) != ip_family(ip2))
+        elog(ERROR, "mismatch in address family (%d)!=(%d)",
+                ip_family(ip), ip_family(ip2));
+    else
+        {
+           int nb = ip_addrsize(ip);
+           unsigned char*pip = ip_addr(ip);
+           unsigned char*pip2 = ip_addr(ip2);
+           unsigned sh = 1;
+
+           while (nb-->0)
+           {
+            res += sh*(pip[nb]-pip2[nb]);
+            sh <<= 8;
+           }
+        }
+
+    PG_RETURN_INT32(res);
+}
+
+static Datum
+i_inet_plusi(inet *ip, int iarg)
+{
+    inet       *dst;
+
+    dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
+    /* make sure any unused bits are zeroed */
+    MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
+
+        {
+           int nb = ip_addrsize(ip);
+           unsigned char*pip = ip_addr(ip);
+           unsigned char*pdst = ip_addr(dst);
+           int carry = 0;
+
+           while (nb-->0)
+           {
+            pdst[nb] = carry = pip[nb]+iarg+carry;
+            iarg >>=8;
+            carry >>=8;
+           }
+        }
+        ip_bits(dst) = ip_bits(ip);
+
+    ip_family(dst) = ip_family(ip);
+    ip_type(dst) = 0;
+    VARATT_SIZEP(dst) = VARHDRSZ
+        + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+        + ip_addrsize(dst);
+
+    PG_RETURN_INET_P(dst);
+}
+
+PG_FUNCTION_INFO_V1(inet_plusi);
+
+Datum
+inet_plusi(PG_FUNCTION_ARGS)
+{
+    inet       *ip = PG_GETARG_INET_P(0);
+    int       iarg = PG_GETARG_INT32(1);
+    return i_inet_plusi(ip,iarg);
+}
+
+PG_FUNCTION_INFO_V1(inet_iplus);
+
+Datum
+inet_iplus(PG_FUNCTION_ARGS)
+{
+    int       iarg = PG_GETARG_INT32(0);
+    inet       *ip = PG_GETARG_INET_P(1);
+    return i_inet_plusi(ip,iarg);
+}
+
+PG_FUNCTION_INFO_V1(inet_mini);
+
+Datum
+inet_mini(PG_FUNCTION_ARGS)
+{
+    inet       *ip = PG_GETARG_INET_P(0);
+    int       iarg = PG_GETARG_INT32(1);
+    return i_inet_plusi(ip,-iarg);
+}
diff -ur xinetops.old/xinetops.sql.in xinetops/xinetops.sql.in
--- xinetops.old/xinetops.sql.in    2005-11-13 12:36:39.000000000 +0100
+++ xinetops/xinetops.sql.in    2005-11-13 12:45:04.000000000 +0100
@@ -0,0 +1,104 @@
+--
+--    PostgreSQL type definitions for extended inet operations.
+--      Copyright (c) 2003-2006, S.R. van den Berg, The Netherlands
+--                               <srb@cuci.nl>
+--
+--      This module is distributed under the same BSD license as PostgreSQL.
+--
+--    $Id: xinetops.sql.in 524 2005-11-13 11:44:43Z srb $
+--
+
+-- Adjust this setting to control where the objects get created.
+SET search_path = public;
+
+SET autocommit TO 'on';
+
+--
+--    The various functions doing the work
+--
+
+CREATE FUNCTION inet_not(inet)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_or(inet, inet)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_and(inet, inet)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_plusi(inet, int)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_iplus(int, inet)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_mini(inet, int)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_min(inet, inet)
+RETURNS int
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+--
+--    Now the operators.
+--
+
+CREATE OPERATOR ~ (
+    RIGHTARG = inet,
+    PROCEDURE = inet_not
+);
+
+CREATE OPERATOR | (
+    LEFTARG = inet,
+    RIGHTARG = inet,
+    COMMUTATOR = |,
+    PROCEDURE = inet_or
+);
+
+CREATE OPERATOR & (
+    LEFTARG = inet,
+    RIGHTARG = inet,
+    COMMUTATOR = &,
+    PROCEDURE = inet_and
+);
+
+CREATE OPERATOR + (
+    LEFTARG = inet,
+    RIGHTARG = int,
+    COMMUTATOR = +,
+    PROCEDURE = inet_plusi
+);
+
+CREATE OPERATOR + (
+    LEFTARG = int,
+    RIGHTARG = inet,
+    COMMUTATOR = +,
+    PROCEDURE = inet_iplus
+);
+
+CREATE OPERATOR - (
+    LEFTARG = inet,
+    RIGHTARG = int,
+    COMMUTATOR = -,
+    PROCEDURE = inet_mini
+);
+
+CREATE OPERATOR - (
+    LEFTARG = inet,
+    RIGHTARG = inet,
+    COMMUTATOR = -,
+    PROCEDURE = inet_min
+);
--
Sincerely,                                                          srb@cuci.nl
           Stephen R. van den Berg (AKA BuGless).

Skiing beyond this point may result in death and/or loss of skiing privileges.

Re: contrib/xinetops for 8.1 "patch"

From
Bruce Momjian
Date:
Stephen R. van den Berg wrote:
> I've been meaning to send it in for a while now, IMHO it could be
> made part of the main distribution as well, but contrib is fine
> if not everyone likes it.
>
> I included the source in patch-format, since I didn't feel comfortable
> attaching a tar.gz file on this list.
> Below is an excerpt from the included README:
> -------------------------------- cut here ---------------------------------
> inet extended operations
> ~~~~~~~~~~~~~~~~~~~~~~~~
>
> This directory contains definitions for extended operators on the
> inet data type.
>
> Operators available are:
>
>    ~ & | + -
>
> It supports the "natural" arithmetic with IP addresses and integers.
> It is useful for applications which have to hand out and administer
> ranges of IP-addresses (like a Radius or DHCP server).

I have modified your original patch to add the code into the main
backend routines.  I added documentation and regression tests as well.

I created only inet functions because family() works on both inet and
cidr, so I assume we are to create just inet versions and cidr will
still work.

Patch needs a catalog version bump.

One unusual issue is because 'inet - inet' returns an int32, you can't
subtract two IPv6 addresses that differ by more than int32.

A larger problem is this:

    test=> SELECT '255.255.255.0'::inet - '1.1.1.1'::inet;
     ?column?
    -----------
     -16843265
    (1 row)

Should subtraction return int8?  Perhaps it is OK because:

    test=> select '255.255.255.0'::inet - (-16843265);
     ?column?
    ----------
     1.1.1.1
    (1 row)

We don't have an unsigned data type.  Of course we also have this
excitement:

    test=> SELECT '255.255.255.0'::inet +  1000000;
      ?column?
    ------------
     0.15.65.64
    (1 row)

so we underflow and overflow cleanly.  Not great, but it works.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.303
diff -c -c -r1.303 func.sgml
*** doc/src/sgml/func.sgml    26 Jan 2006 02:35:48 -0000    1.303
--- doc/src/sgml/func.sgml    9 Feb 2006 20:18:40 -0000
***************
*** 6787,6792 ****
--- 6787,6822 ----
          <entry>contains or equals</entry>
          <entry><literal>inet '192.168.1/24' >>= inet '192.168.1/24'</literal></entry>
         </row>
+        <row>
+         <entry> <literal>~</literal> </entry>
+         <entry>bitwise NOT</entry>
+         <entry><literal>~ inet '192.168.1.6'</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>&</literal> </entry>
+         <entry>bitwise AND</entry>
+         <entry><literal>inet '192.168.1.6' & inet '0.0.0.255'</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>|</literal> </entry>
+         <entry>bitwise OR</entry>
+         <entry><literal>inet '192.168.1.6' | inet '0.0.0.255'</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>+</literal> </entry>
+         <entry>addition</entry>
+         <entry><literal>inet '192.168.1.6' + 25</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>-</literal> </entry>
+         <entry>subtraction</entry>
+         <entry><literal>inet '192.168.1.43' - 36</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>-</literal> </entry>
+         <entry>subtraction</entry>
+         <entry><literal>inet '192.168.1.43' - inet '192.168.1.19'</literal></entry>
+        </row>
        </tbody>
       </tgroup>
      </table>
Index: src/backend/utils/adt/network.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/network.c,v
retrieving revision 1.63
diff -c -c -r1.63 network.c
*** src/backend/utils/adt/network.c    7 Feb 2006 17:04:04 -0000    1.63
--- src/backend/utils/adt/network.c    9 Feb 2006 20:18:43 -0000
***************
*** 27,32 ****
--- 27,33 ----
  static int    bitncmp(void *l, void *r, int n);
  static bool addressOK(unsigned char *a, int bits, int family);
  static int    ip_addrsize(inet *inetptr);
+ static Datum internal_inetpl(inet *ip, int iarg);

  /*
   *    Access macros.
***************
*** 1250,1252 ****
--- 1251,1441 ----

      PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
  }
+
+
+ Datum
+ inetnot(PG_FUNCTION_ARGS)
+ {
+     inet       *ip = PG_GETARG_INET_P(0);
+     inet       *dst;
+
+     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+     {
+         int nb = ip_addrsize(ip);
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pdst = ip_addr(dst);
+
+         while (nb-- > 0)
+             pdst[nb] = ~pip[nb];
+     }
+     ip_bits(dst) = ip_bits(ip);
+
+     ip_family(dst) = ip_family(ip);
+     VARATT_SIZEP(dst) = VARHDRSZ +
+         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
+         ip_addrsize(dst);
+
+     PG_RETURN_INET_P(dst);
+ }
+
+
+ Datum
+ inetand(PG_FUNCTION_ARGS)
+ {
+     inet       *ip = PG_GETARG_INET_P(0);
+     inet       *ip2 = PG_GETARG_INET_P(1);
+     inet       *dst;
+
+     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+     if (ip_family(ip) != ip_family(ip2))
+         ereport(ERROR,
+                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                  errmsg("mismatch in address family (%d) != (%d)",
+                         ip_family(ip), ip_family(ip2))));
+     else
+     {
+         int nb = ip_addrsize(ip);
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pip2 = ip_addr(ip2);
+         unsigned char    *pdst = ip_addr(dst);
+
+         while (nb-- > 0)
+             pdst[nb] = pip[nb] & pip2[nb];
+     }
+     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
+
+     ip_family(dst) = ip_family(ip);
+     VARATT_SIZEP(dst) = VARHDRSZ +
+         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
+         ip_addrsize(dst);
+
+     PG_RETURN_INET_P(dst);
+ }
+
+
+ Datum
+ inetor(PG_FUNCTION_ARGS)
+ {
+     inet       *ip = PG_GETARG_INET_P(0);
+     inet       *ip2 = PG_GETARG_INET_P(1);
+     inet       *dst;
+
+     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+     if (ip_family(ip) != ip_family(ip2))
+         ereport(ERROR,
+                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                  errmsg("mismatch in address family (%d) != (%d)",
+                         ip_family(ip), ip_family(ip2))));
+     else
+     {
+         int nb = ip_addrsize(ip);
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pip2 = ip_addr(ip2);
+         unsigned char    *pdst = ip_addr(dst);
+
+         while (nb-- > 0)
+             pdst[nb] = pip[nb] | pip2[nb];
+     }
+     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
+
+     ip_family(dst) = ip_family(ip);
+     VARATT_SIZEP(dst) = VARHDRSZ +
+         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
+         ip_addrsize(dst);
+
+     PG_RETURN_INET_P(dst);
+ }
+
+
+ static Datum
+ internal_inetpl(inet *ip, int plus)
+ {
+     inet       *dst;
+
+     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+     {
+         int nb = ip_addrsize(ip);
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pdst = ip_addr(dst);
+         int carry = 0;
+
+         while (nb-- > 0)
+         {
+             pdst[nb] = carry = pip[nb] + (plus & 0xff) + carry;
+             plus >>= 8;        /* process next byte */
+             carry >>= 8;    /* remove low byte */
+         }
+     }
+     ip_bits(dst) = ip_bits(ip);
+
+     ip_family(dst) = ip_family(ip);
+     VARATT_SIZEP(dst) = VARHDRSZ +
+         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
+         ip_addrsize(dst);
+
+     PG_RETURN_INET_P(dst);
+ }
+
+
+ Datum
+ inetpl(PG_FUNCTION_ARGS)
+ {
+     inet   *ip = PG_GETARG_INET_P(0);
+     int32    plus = PG_GETARG_INT32(1);
+
+     return internal_inetpl(ip, plus);
+ }
+
+
+ Datum
+ inetmi_int4(PG_FUNCTION_ARGS)
+ {
+     inet   *ip = PG_GETARG_INET_P(0);
+     int32    plus = PG_GETARG_INT32(1);
+
+     return internal_inetpl(ip, -plus);
+ }
+
+
+ Datum
+ inetmi(PG_FUNCTION_ARGS)
+ {
+     inet       *ip = PG_GETARG_INET_P(0);
+     inet       *ip2 = PG_GETARG_INET_P(1);
+     int32        res = 0;
+
+     if (ip_family(ip) != ip_family(ip2))
+         ereport(ERROR,
+                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                  errmsg("mismatch in address family (%d) != (%d)",
+                         ip_family(ip), ip_family(ip2))));
+     else
+     {
+         int nb = ip_addrsize(ip);
+         int    byte = 0;
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pip2 = ip_addr(ip2);
+
+         while (nb-- > 0)
+         {
+             if (byte >= sizeof(int32))
+             {
+                 /* Error on IPv6 subtraction when bytes beyond int32 differ */
+                 if (pip[nb] != pip2[nb])
+                     ereport(ERROR,
+                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                              errmsg("result out of range")));
+             }
+             else
+                 res += (pip[nb] - pip2[nb]) << (byte * 8);
+
+             byte++;
+         }
+     }
+
+     PG_RETURN_INT32(res);
+ }
Index: src/include/catalog/pg_operator.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_operator.h,v
retrieving revision 1.138
diff -c -c -r1.138 pg_operator.h
*** src/include/catalog/pg_operator.h    26 Jan 2006 02:35:49 -0000    1.138
--- src/include/catalog/pg_operator.h    9 Feb 2006 20:18:45 -0000
***************
*** 653,658 ****
--- 653,667 ----
  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

+ DATA(insert OID = 2634 (  "~"       PGNSP PGUID l f    0 869 869 0 0 0 0 0 0 inetnot - - ));
+ DATA(insert OID = 2635 (  "&"       PGNSP PGUID b f    869 869 869 0 0 0 0 0 0 inetand - - ));
+ DATA(insert OID = 2636 (  "|"       PGNSP PGUID b f    869 869 869 0 0 0 0 0 0 inetor - - ));
+ DATA(insert OID = 2637 (  "+"       PGNSP PGUID b f    869 23 869 2638 0 0 0 0 0 inetpl - - ));
+ DATA(insert OID = 2638 (  "+"       PGNSP PGUID b f    23 869 869 2637 0 0 0 0 0 int4pl_inet - - ));
+ DATA(insert OID = 2639 (  "-"       PGNSP PGUID b f    869 23 869 0 0 0 0 0 0 inetmi_int4 - - ));
+ DATA(insert OID = 2640 (  "-"       PGNSP PGUID b f    869 869 23 0 0 0 0 0 0 inetmi - - ));
+
+
  /* 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: src/include/catalog/pg_proc.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.394
diff -c -c -r1.394 pg_proc.h
*** src/include/catalog/pg_proc.h    9 Feb 2006 14:53:51 -0000    1.394
--- src/include/catalog/pg_proc.h    9 Feb 2006 20:18:50 -0000
***************
*** 2431,2436 ****
--- 2431,2451 ----
  DATA(insert OID = 2199 (  inet_server_port        PGNSP PGUID 12 f f f f s 0 23 "" _null_ _null_ _null_
inet_server_port- _null_ )); 
  DESCR("server's port number for this connection");

+ DATA(insert OID = 2627 (  inetnot            PGNSP PGUID 12 f f t f i 1 869 "869" _null_ _null_ _null_    inetnot -
_null_)); 
+ DESCR("binary NOT");
+ DATA(insert OID = 2628 (  inetand            PGNSP PGUID 12 f f t f i 2 869 "869 869" _null_ _null_ _null_    inetand
-_null_ )); 
+ DESCR("binary AND");
+ DATA(insert OID = 2629 (  inetor            PGNSP PGUID 12 f f t f i 2 869 "869 869" _null_ _null_ _null_    inetor -
_null_)); 
+ DESCR("binary OR");
+ DATA(insert OID = 2630 (  inetpl            PGNSP PGUID 12 f f t f i 2 869 "869 23" _null_ _null_ _null_    inetpl -
_null_)); 
+ DESCR("add integer to INET value");
+ DATA(insert OID = 2631 ( int4pl_inet        PGNSP PGUID 14 f f t f i 2 869 "23 869" _null_ _null_ _null_    "select
$2+ $1" - _null_ )); 
+ DESCR("add integer to INET value");
+ DATA(insert OID = 2632 (  inetmi_int4        PGNSP PGUID 12 f f t f i 2 869 "869 23" _null_ _null_ _null_
inetmi_int4- _null_ )); 
+ DESCR("subtract integer from INET value");
+ DATA(insert OID = 2633 (  inetmi            PGNSP PGUID 12 f f t f i 2 23 "869 869" _null_ _null_ _null_    inetmi -
_null_)); 
+ DESCR("subtract INET values");
+
  DATA(insert OID = 1686 ( numeric            PGNSP PGUID 12 f f t f i 1 1700 "25" _null_ _null_ _null_ text_numeric -
_null_)); 
  DESCR("(internal)");
  DATA(insert OID = 1688 ( text                PGNSP PGUID 12 f f t f i 1 25 "1700" _null_ _null_ _null_ numeric_text -
_null_)); 
Index: src/include/utils/builtins.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.272
diff -c -c -r1.272 builtins.h
*** src/include/utils/builtins.h    26 Jan 2006 02:35:50 -0000    1.272
--- src/include/utils/builtins.h    9 Feb 2006 20:18:51 -0000
***************
*** 734,739 ****
--- 734,745 ----
  extern Datum inet_client_port(PG_FUNCTION_ARGS);
  extern Datum inet_server_addr(PG_FUNCTION_ARGS);
  extern Datum inet_server_port(PG_FUNCTION_ARGS);
+ extern Datum inetnot(PG_FUNCTION_ARGS);
+ extern Datum inetand(PG_FUNCTION_ARGS);
+ extern Datum inetor(PG_FUNCTION_ARGS);
+ extern Datum inetpl(PG_FUNCTION_ARGS);
+ extern Datum inetmi_int4(PG_FUNCTION_ARGS);
+ extern Datum inetmi(PG_FUNCTION_ARGS);

  /* mac.c */
  extern Datum macaddr_in(PG_FUNCTION_ARGS);
Index: src/test/regress/expected/inet.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/inet.out,v
retrieving revision 1.19
diff -c -c -r1.19 inet.out
*** src/test/regress/expected/inet.out    8 Oct 2004 01:45:37 -0000    1.19
--- src/test/regress/expected/inet.out    9 Feb 2006 20:18:52 -0000
***************
*** 240,244 ****
--- 240,381 ----
   192.168.1.0/26 | 192.168.1.226
  (6 rows)

+ SELECT ~i FROM inet_tbl;
+                   ?column?
+ --------------------------------------------
+  63.87.254.29/24
+  63.87.254.29
+  63.87.254.255/24
+  63.87.254.255/25
+  63.87.254.0/24
+  63.87.254.0/25
+  245.254.253.252/8
+  245.254.253.252/8
+  245.254.253.252
+  245.254.253.252/24
+  245.254.253.252/16
+  245.254.253.252/8
+  244.254.253.252/8
+  246.254.253.252/8
+  ffef:ffdc:ffff:ffff:ffff:ffff:ffff:ff0e/64
+  ffef:ffdc:ffff:ffff:ffff:ffff:ffff:0
+  ffff:ffff:ffff:ffff:ffff:ffff:fbfc:fdfe/24
+ (17 rows)
+
+ SELECT i & c FROM inet_tbl;
+     ?column?
+ ----------------
+  192.168.1.0/24
+  192.168.1.0
+  192.168.1.0/24
+  192.168.1.0/25
+  192.168.1.0/24
+  192.168.1.0/25
+  10.0.0.0/8
+  10.0.0.0
+  10.1.2.3
+  10.1.2.0/24
+  10.1.0.0/16
+  10.0.0.0/8
+  10.0.0.0/8
+  8.0.0.0/8
+  10:23::f1
+  10:23::8000
+  ::0.2.2.0
+ (17 rows)
+
+ SELECT i | c FROM inet_tbl;
+      ?column?
+ ------------------
+  192.168.1.226/24
+  192.168.1.226
+  192.168.1.0/24
+  192.168.1.0/25
+  192.168.1.255/24
+  192.168.1.255/25
+  10.1.2.3/8
+  10.1.2.3
+  10.1.2.3
+  10.1.2.3/24
+  10.1.2.3/16
+  10.1.2.3/8
+  11.1.2.3/8
+  11.1.2.3/8
+  10:23::f1
+  10:23::ffff
+  ::ffff:5.3.3.5
+ (17 rows)
+
+ SELECT i + 5000 FROM inet_tbl;
+      ?column?
+ -------------------
+  192.168.21.106/24
+  192.168.21.106
+  192.168.20.136/24
+  192.168.20.136/25
+  192.168.21.135/24
+  192.168.21.135/25
+  10.1.21.139/8
+  10.1.21.139/8
+  10.1.21.139
+  10.1.21.139/24
+  10.1.21.139/16
+  10.1.21.139/8
+  11.1.21.139/8
+  9.1.21.139/8
+  10:23::1479/64
+  10:23::1:1387
+  ::4.3.21.137/24
+ (17 rows)
+
+ SELECT i - 5000 FROM inet_tbl;
+                 ?column?
+ ----------------------------------------
+  192.167.238.90/24
+  192.167.238.90
+  192.167.237.120/24
+  192.167.237.120/25
+  192.167.238.119/24
+  192.167.238.119/25
+  10.0.238.123/8
+  10.0.238.123/8
+  10.0.238.123
+  10.0.238.123/24
+  10.0.238.123/16
+  10.0.238.123/8
+  11.0.238.123/8
+  9.0.238.123/8
+  10:22:ffff:ffff:ffff:ffff:ffff:ed69/64
+  10:23::ec77
+  ::4.2.238.121/24
+ (17 rows)
+
+ SELECT i - c FROM inet_tbl where family(i) = 4;
+  ?column?
+ -----------
+        226
+        226
+          0
+          0
+        255
+        255
+      66051
+      66051
+          0
+          3
+        515
+      66051
+   16843267
+  -16711165
+ (14 rows)
+
+ SELECT (inet '::ffff:1.2.3.4/128') - (inet '::ffff:1.1.1.1/128');
+  ?column?
+ ----------
+     66051
+ (1 row)
+
+ SELECT (inet '::ffff:1.1.1.1/128') - (inet '::1/128');
+ ERROR:  result out of range
  SET enable_seqscan TO on;
  DROP INDEX inet_idx1;
Index: src/test/regress/sql/inet.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/inet.sql,v
retrieving revision 1.11
diff -c -c -r1.11 inet.sql
*** src/test/regress/sql/inet.sql    8 Oct 2004 01:45:37 -0000    1.11
--- src/test/regress/sql/inet.sql    9 Feb 2006 20:18:52 -0000
***************
*** 62,67 ****
--- 62,77 ----
  SET enable_seqscan TO off;
  SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr;
  SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
+
+ SELECT ~i FROM inet_tbl;
+ SELECT i & c FROM inet_tbl;
+ SELECT i | c FROM inet_tbl;
+ SELECT i + 5000 FROM inet_tbl;
+ SELECT i - 5000 FROM inet_tbl;
+ SELECT i - c FROM inet_tbl where family(i) = 4;
+ SELECT (inet '::ffff:1.2.3.4/128') - (inet '::ffff:1.1.1.1/128');
+ SELECT (inet '::ffff:1.1.1.1/128') - (inet '::1/128');
+
  SET enable_seqscan TO on;
  DROP INDEX inet_idx1;


Re: contrib/xinetops for 8.1 "patch"

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> A larger problem is this:

>     test=> SELECT '255.255.255.0'::inet - '1.1.1.1'::inet;
>      ?column?
>     -----------
>      -16843265
>     (1 row)

> Should subtraction return int8?

Probably, and for that matter the addition operators should take int8;
on IPV6 data even that's not really wide enough.

> We don't have an unsigned data type.  Of course we also have this
> excitement:

>     test=> SELECT '255.255.255.0'::inet +  1000000;
>       ?column?
>     ------------
>      0.15.65.64
>     (1 row)

> so we underflow and overflow cleanly.  Not great, but it works.

"Cleanly" isn't the adjective I'd use for that.  There should be an
overflow error.

            regards, tom lane

Re: contrib/xinetops for 8.1 "patch"

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > A larger problem is this:
>
> >     test=> SELECT '255.255.255.0'::inet - '1.1.1.1'::inet;
> >      ?column?
> >     -----------
> >      -16843265
> >     (1 row)
>
> > Should subtraction return int8?
>
> Probably, and for that matter the addition operators should take int8;
> on IPV6 data even that's not really wide enough.
>
> > We don't have an unsigned data type.  Of course we also have this
> > excitement:
>
> >     test=> SELECT '255.255.255.0'::inet +  1000000;
> >       ?column?
> >     ------------
> >      0.15.65.64
> >     (1 row)
>
> > so we underflow and overflow cleanly.  Not great, but it works.
>
> "Cleanly" isn't the adjective I'd use for that.  There should be an
> overflow error.

OK, changed to int8, and overflow checks added.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.303
diff -c -c -r1.303 func.sgml
*** doc/src/sgml/func.sgml    26 Jan 2006 02:35:48 -0000    1.303
--- doc/src/sgml/func.sgml    10 Feb 2006 04:11:52 -0000
***************
*** 6787,6792 ****
--- 6787,6822 ----
          <entry>contains or equals</entry>
          <entry><literal>inet '192.168.1/24' >>= inet '192.168.1/24'</literal></entry>
         </row>
+        <row>
+         <entry> <literal>~</literal> </entry>
+         <entry>bitwise NOT</entry>
+         <entry><literal>~ inet '192.168.1.6'</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>&</literal> </entry>
+         <entry>bitwise AND</entry>
+         <entry><literal>inet '192.168.1.6' & inet '0.0.0.255'</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>|</literal> </entry>
+         <entry>bitwise OR</entry>
+         <entry><literal>inet '192.168.1.6' | inet '0.0.0.255'</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>+</literal> </entry>
+         <entry>addition</entry>
+         <entry><literal>inet '192.168.1.6' + 25</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>-</literal> </entry>
+         <entry>subtraction</entry>
+         <entry><literal>inet '192.168.1.43' - 36</literal></entry>
+        </row>
+        <row>
+         <entry> <literal>-</literal> </entry>
+         <entry>subtraction</entry>
+         <entry><literal>inet '192.168.1.43' - inet '192.168.1.19'</literal></entry>
+        </row>
        </tbody>
       </tgroup>
      </table>
Index: src/backend/utils/adt/network.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/network.c,v
retrieving revision 1.63
diff -c -c -r1.63 network.c
*** src/backend/utils/adt/network.c    7 Feb 2006 17:04:04 -0000    1.63
--- src/backend/utils/adt/network.c    10 Feb 2006 04:11:57 -0000
***************
*** 27,32 ****
--- 27,33 ----
  static int    bitncmp(void *l, void *r, int n);
  static bool addressOK(unsigned char *a, int bits, int family);
  static int    ip_addrsize(inet *inetptr);
+ static Datum internal_inetpl(inet *ip, int64 iarg);

  /*
   *    Access macros.
***************
*** 1250,1252 ****
--- 1251,1458 ----

      PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
  }
+
+
+ Datum
+ inetnot(PG_FUNCTION_ARGS)
+ {
+     inet       *ip = PG_GETARG_INET_P(0);
+     inet       *dst;
+
+     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+     {
+         int nb = ip_addrsize(ip);
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pdst = ip_addr(dst);
+
+         while (nb-- > 0)
+             pdst[nb] = ~pip[nb];
+     }
+     ip_bits(dst) = ip_bits(ip);
+
+     ip_family(dst) = ip_family(ip);
+     VARATT_SIZEP(dst) = VARHDRSZ +
+         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
+         ip_addrsize(dst);
+
+     PG_RETURN_INET_P(dst);
+ }
+
+
+ Datum
+ inetand(PG_FUNCTION_ARGS)
+ {
+     inet       *ip = PG_GETARG_INET_P(0);
+     inet       *ip2 = PG_GETARG_INET_P(1);
+     inet       *dst;
+
+     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+     if (ip_family(ip) != ip_family(ip2))
+         ereport(ERROR,
+                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                  errmsg("mismatch in address family (%d) != (%d)",
+                         ip_family(ip), ip_family(ip2))));
+     else
+     {
+         int nb = ip_addrsize(ip);
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pip2 = ip_addr(ip2);
+         unsigned char    *pdst = ip_addr(dst);
+
+         while (nb-- > 0)
+             pdst[nb] = pip[nb] & pip2[nb];
+     }
+     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
+
+     ip_family(dst) = ip_family(ip);
+     VARATT_SIZEP(dst) = VARHDRSZ +
+         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
+         ip_addrsize(dst);
+
+     PG_RETURN_INET_P(dst);
+ }
+
+
+ Datum
+ inetor(PG_FUNCTION_ARGS)
+ {
+     inet       *ip = PG_GETARG_INET_P(0);
+     inet       *ip2 = PG_GETARG_INET_P(1);
+     inet       *dst;
+
+     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+     if (ip_family(ip) != ip_family(ip2))
+         ereport(ERROR,
+                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                  errmsg("mismatch in address family (%d) != (%d)",
+                         ip_family(ip), ip_family(ip2))));
+     else
+     {
+         int nb = ip_addrsize(ip);
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pip2 = ip_addr(ip2);
+         unsigned char    *pdst = ip_addr(dst);
+
+         while (nb-- > 0)
+             pdst[nb] = pip[nb] | pip2[nb];
+     }
+     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
+
+     ip_family(dst) = ip_family(ip);
+     VARATT_SIZEP(dst) = VARHDRSZ +
+         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
+         ip_addrsize(dst);
+
+     PG_RETURN_INET_P(dst);
+ }
+
+
+ static Datum
+ internal_inetpl(inet *ip, int64 plus)
+ {
+     inet       *dst;
+
+     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+     {
+         int nb = ip_addrsize(ip);
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pdst = ip_addr(dst);
+         int carry = 0;
+
+         while (nb-- > 0)
+         {
+             pdst[nb] = carry = pip[nb] + plus + carry;
+             plus /= 0x100;        /* process next byte */
+             carry /= 0x100;        /* remove low byte */
+             /* Overflow on high byte? */
+             if (nb == 0 && (plus != 0 || carry != 0))
+                 ereport(ERROR,
+                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                          errmsg("result out of range")));
+         }
+     }
+     ip_bits(dst) = ip_bits(ip);
+
+     ip_family(dst) = ip_family(ip);
+     VARATT_SIZEP(dst) = VARHDRSZ +
+         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
+         ip_addrsize(dst);
+
+     PG_RETURN_INET_P(dst);
+ }
+
+
+ Datum
+ inetpl(PG_FUNCTION_ARGS)
+ {
+     inet   *ip = PG_GETARG_INET_P(0);
+     int64    plus = PG_GETARG_INT64(1);
+
+     return internal_inetpl(ip, plus);
+ }
+
+
+ Datum
+ inetmi_int8(PG_FUNCTION_ARGS)
+ {
+     inet   *ip = PG_GETARG_INET_P(0);
+     int64    plus = PG_GETARG_INT64(1);
+
+     return internal_inetpl(ip, -plus);
+ }
+
+
+ Datum
+ inetmi(PG_FUNCTION_ARGS)
+ {
+     inet       *ip = PG_GETARG_INET_P(0);
+     inet       *ip2 = PG_GETARG_INET_P(1);
+     int64        res = 0;
+
+     if (ip_family(ip) != ip_family(ip2))
+         ereport(ERROR,
+                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                  errmsg("mismatch in address family (%d) != (%d)",
+                         ip_family(ip), ip_family(ip2))));
+     else
+     {
+         int nb = ip_addrsize(ip);
+         int    byte = 0;
+         unsigned char    *pip = ip_addr(ip);
+         unsigned char    *pip2 = ip_addr(ip2);
+
+         while (nb-- > 0)
+         {
+             /*
+              *    Error if overflow on last byte.  This test is tricky
+              *    because if the subtraction == 128 and res is negative, or
+              *    if subtraction == -128 and res is positive, the result
+              *    would still fit in int64.
+              */
+             if (byte + 1 == sizeof(int64) &&
+                 (pip[nb] - pip2[nb] >= 128 + (res < 0) ||
+                  pip[nb] - pip2[nb] <= -128 - (res > 0)))
+                 ereport(ERROR,
+                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                          errmsg("result out of range")));
+             if (byte >= sizeof(int64))
+             {
+                 /* Error if bytes beyond int64 length differ. */
+                 if (pip[nb] != pip2[nb])
+                     ereport(ERROR,
+                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                              errmsg("result out of range")));
+             }
+             else
+                 res += (int64)(pip[nb] - pip2[nb]) << (byte * 8);
+
+             byte++;
+         }
+     }
+
+     PG_RETURN_INT64(res);
+ }
Index: src/include/catalog/pg_operator.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_operator.h,v
retrieving revision 1.138
diff -c -c -r1.138 pg_operator.h
*** src/include/catalog/pg_operator.h    26 Jan 2006 02:35:49 -0000    1.138
--- src/include/catalog/pg_operator.h    10 Feb 2006 04:11:59 -0000
***************
*** 653,658 ****
--- 653,667 ----
  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

+ DATA(insert OID = 2634 (  "~"       PGNSP PGUID l f    0 869 869 0 0 0 0 0 0 inetnot - - ));
+ DATA(insert OID = 2635 (  "&"       PGNSP PGUID b f    869 869 869 0 0 0 0 0 0 inetand - - ));
+ DATA(insert OID = 2636 (  "|"       PGNSP PGUID b f    869 869 869 0 0 0 0 0 0 inetor - - ));
+ DATA(insert OID = 2637 (  "+"       PGNSP PGUID b f    869 20 869 2638 0 0 0 0 0 inetpl - - ));
+ DATA(insert OID = 2638 (  "+"       PGNSP PGUID b f    20 869 869 2637 0 0 0 0 0 int8pl_inet - - ));
+ DATA(insert OID = 2639 (  "-"       PGNSP PGUID b f    869 20 869 0 0 0 0 0 0 inetmi_int8 - - ));
+ DATA(insert OID = 2640 (  "-"       PGNSP PGUID b f    869 869 20 0 0 0 0 0 0 inetmi - - ));
+
+
  /* 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: src/include/catalog/pg_proc.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.394
diff -c -c -r1.394 pg_proc.h
*** src/include/catalog/pg_proc.h    9 Feb 2006 14:53:51 -0000    1.394
--- src/include/catalog/pg_proc.h    10 Feb 2006 04:12:03 -0000
***************
*** 2431,2436 ****
--- 2431,2451 ----
  DATA(insert OID = 2199 (  inet_server_port        PGNSP PGUID 12 f f f f s 0 23 "" _null_ _null_ _null_
inet_server_port- _null_ )); 
  DESCR("server's port number for this connection");

+ DATA(insert OID = 2627 (  inetnot            PGNSP PGUID 12 f f t f i 1 869 "869" _null_ _null_ _null_    inetnot -
_null_)); 
+ DESCR("binary NOT");
+ DATA(insert OID = 2628 (  inetand            PGNSP PGUID 12 f f t f i 2 869 "869 869" _null_ _null_ _null_    inetand
-_null_ )); 
+ DESCR("binary AND");
+ DATA(insert OID = 2629 (  inetor            PGNSP PGUID 12 f f t f i 2 869 "869 869" _null_ _null_ _null_    inetor -
_null_)); 
+ DESCR("binary OR");
+ DATA(insert OID = 2630 (  inetpl            PGNSP PGUID 12 f f t f i 2 869 "869 20" _null_ _null_ _null_    inetpl -
_null_)); 
+ DESCR("add integer to INET value");
+ DATA(insert OID = 2631 ( int8pl_inet        PGNSP PGUID 14 f f t f i 2 869 "20 869" _null_ _null_ _null_    "select
$2+ $1" - _null_ )); 
+ DESCR("add integer to INET value");
+ DATA(insert OID = 2632 (  inetmi_int8        PGNSP PGUID 12 f f t f i 2 869 "869 20" _null_ _null_ _null_
inetmi_int8- _null_ )); 
+ DESCR("subtract integer from INET value");
+ DATA(insert OID = 2633 (  inetmi            PGNSP PGUID 12 f f t f i 2 20 "869 869" _null_ _null_ _null_    inetmi -
_null_)); 
+ DESCR("subtract INET values");
+
  DATA(insert OID = 1686 ( numeric            PGNSP PGUID 12 f f t f i 1 1700 "25" _null_ _null_ _null_ text_numeric -
_null_)); 
  DESCR("(internal)");
  DATA(insert OID = 1688 ( text                PGNSP PGUID 12 f f t f i 1 25 "1700" _null_ _null_ _null_ numeric_text -
_null_)); 
Index: src/include/utils/builtins.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.272
diff -c -c -r1.272 builtins.h
*** src/include/utils/builtins.h    26 Jan 2006 02:35:50 -0000    1.272
--- src/include/utils/builtins.h    10 Feb 2006 04:12:04 -0000
***************
*** 734,739 ****
--- 734,745 ----
  extern Datum inet_client_port(PG_FUNCTION_ARGS);
  extern Datum inet_server_addr(PG_FUNCTION_ARGS);
  extern Datum inet_server_port(PG_FUNCTION_ARGS);
+ extern Datum inetnot(PG_FUNCTION_ARGS);
+ extern Datum inetand(PG_FUNCTION_ARGS);
+ extern Datum inetor(PG_FUNCTION_ARGS);
+ extern Datum inetpl(PG_FUNCTION_ARGS);
+ extern Datum inetmi_int8(PG_FUNCTION_ARGS);
+ extern Datum inetmi(PG_FUNCTION_ARGS);

  /* mac.c */
  extern Datum macaddr_in(PG_FUNCTION_ARGS);
Index: src/test/regress/expected/inet.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/inet.out,v
retrieving revision 1.19
diff -c -c -r1.19 inet.out
*** src/test/regress/expected/inet.out    8 Oct 2004 01:45:37 -0000    1.19
--- src/test/regress/expected/inet.out    10 Feb 2006 04:12:05 -0000
***************
*** 240,244 ****
--- 240,376 ----
   192.168.1.0/26 | 192.168.1.226
  (6 rows)

+ SELECT ~i FROM inet_tbl;
+                   ?column?
+ --------------------------------------------
+  63.87.254.29/24
+  63.87.254.29
+  63.87.254.255/24
+  63.87.254.255/25
+  63.87.254.0/24
+  63.87.254.0/25
+  245.254.253.252/8
+  245.254.253.252/8
+  245.254.253.252
+  245.254.253.252/24
+  245.254.253.252/16
+  245.254.253.252/8
+  244.254.253.252/8
+  246.254.253.252/8
+  ffef:ffdc:ffff:ffff:ffff:ffff:ffff:ff0e/64
+  ffef:ffdc:ffff:ffff:ffff:ffff:ffff:0
+  ffff:ffff:ffff:ffff:ffff:ffff:fbfc:fdfe/24
+ (17 rows)
+
+ SELECT i & c FROM inet_tbl;
+     ?column?
+ ----------------
+  192.168.1.0/24
+  192.168.1.0
+  192.168.1.0/24
+  192.168.1.0/25
+  192.168.1.0/24
+  192.168.1.0/25
+  10.0.0.0/8
+  10.0.0.0
+  10.1.2.3
+  10.1.2.0/24
+  10.1.0.0/16
+  10.0.0.0/8
+  10.0.0.0/8
+  8.0.0.0/8
+  10:23::f1
+  10:23::8000
+  ::0.2.2.0
+ (17 rows)
+
+ SELECT i | c FROM inet_tbl;
+      ?column?
+ ------------------
+  192.168.1.226/24
+  192.168.1.226
+  192.168.1.0/24
+  192.168.1.0/25
+  192.168.1.255/24
+  192.168.1.255/25
+  10.1.2.3/8
+  10.1.2.3
+  10.1.2.3
+  10.1.2.3/24
+  10.1.2.3/16
+  10.1.2.3/8
+  11.1.2.3/8
+  11.1.2.3/8
+  10:23::f1
+  10:23::ffff
+  ::ffff:5.3.3.5
+ (17 rows)
+
+ SELECT i + 500 FROM inet_tbl;
+      ?column?
+ ------------------
+  192.168.4.214/24
+  192.168.4.214
+  192.168.3.244/24
+  192.168.3.244/25
+  192.168.4.243/24
+  192.168.4.243/25
+  10.1.4.247/8
+  10.1.4.247/8
+  10.1.4.247
+  10.1.4.247/24
+  10.1.4.247/16
+  10.1.4.247/8
+  11.1.4.247/8
+  9.1.4.247/8
+  10:23::3e5/64
+  10:23::1:2f3
+  ::4.3.4.245/24
+ (17 rows)
+
+ SELECT i - 500 FROM inet_tbl;
+                 ?column?
+ --------------------
+  192.168.255.238/24
+  192.168.255.238
+  192.168.255.12/24
+  192.168.255.12/25
+  192.168.0.11/24
+  192.168.0.11/25
+  10.1.0.15/8
+  10.1.0.15/8
+  10.1.0.15
+  10.1.0.15/24
+  10.1.0.15/16
+  10.1.0.15/8
+  11.1.0.15/8
+  9.1.0.15/8
+  10:23::fefd/64
+  10:23::fe0b
+  ::4.3.0.13/24
+ (17 rows)
+
+ SELECT i - c FROM inet_tbl;
+  ?column?
+ ------------------
+        226
+        226
+          0
+          0
+        255
+        255
+      66051
+      66051
+          0
+          3
+        515
+      66051
+   16843267
+  -16711165
+                 0
+             32767
+  -281470631346435
+ (17 rows)
+
  SET enable_seqscan TO on;
  DROP INDEX inet_idx1;
Index: src/test/regress/sql/inet.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/inet.sql,v
retrieving revision 1.11
diff -c -c -r1.11 inet.sql
*** src/test/regress/sql/inet.sql    8 Oct 2004 01:45:37 -0000    1.11
--- src/test/regress/sql/inet.sql    10 Feb 2006 04:12:05 -0000
***************
*** 62,67 ****
--- 62,75 ----
  SET enable_seqscan TO off;
  SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr;
  SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
+
+ SELECT ~i FROM inet_tbl;
+ SELECT i & c FROM inet_tbl;
+ SELECT i | c FROM inet_tbl;
+ SELECT i + 500 FROM inet_tbl;
+ SELECT i - 500 FROM inet_tbl;
+ SELECT i - c FROM inet_tbl;
+
  SET enable_seqscan TO on;
  DROP INDEX inet_idx1;


Re: contrib/xinetops for 8.1 "patch"

From
Bruce Momjian
Date:
Patch applied.  Thanks.

---------------------------------------------------------------------------


Bruce Momjian wrote:
> Tom Lane wrote:
> > Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > > A larger problem is this:
> >
> > >     test=> SELECT '255.255.255.0'::inet - '1.1.1.1'::inet;
> > >      ?column?
> > >     -----------
> > >      -16843265
> > >     (1 row)
> >
> > > Should subtraction return int8?
> >
> > Probably, and for that matter the addition operators should take int8;
> > on IPV6 data even that's not really wide enough.
> >
> > > We don't have an unsigned data type.  Of course we also have this
> > > excitement:
> >
> > >     test=> SELECT '255.255.255.0'::inet +  1000000;
> > >       ?column?
> > >     ------------
> > >      0.15.65.64
> > >     (1 row)
> >
> > > so we underflow and overflow cleanly.  Not great, but it works.
> >
> > "Cleanly" isn't the adjective I'd use for that.  There should be an
> > overflow error.
>
> OK, changed to int8, and overflow checks added.
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

> Index: doc/src/sgml/func.sgml
> ===================================================================
> RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v
> retrieving revision 1.303
> diff -c -c -r1.303 func.sgml
> *** doc/src/sgml/func.sgml    26 Jan 2006 02:35:48 -0000    1.303
> --- doc/src/sgml/func.sgml    10 Feb 2006 04:11:52 -0000
> ***************
> *** 6787,6792 ****
> --- 6787,6822 ----
>           <entry>contains or equals</entry>
>           <entry><literal>inet '192.168.1/24' >>= inet '192.168.1/24'</literal></entry>
>          </row>
> +        <row>
> +         <entry> <literal>~</literal> </entry>
> +         <entry>bitwise NOT</entry>
> +         <entry><literal>~ inet '192.168.1.6'</literal></entry>
> +        </row>
> +        <row>
> +         <entry> <literal>&</literal> </entry>
> +         <entry>bitwise AND</entry>
> +         <entry><literal>inet '192.168.1.6' & inet '0.0.0.255'</literal></entry>
> +        </row>
> +        <row>
> +         <entry> <literal>|</literal> </entry>
> +         <entry>bitwise OR</entry>
> +         <entry><literal>inet '192.168.1.6' | inet '0.0.0.255'</literal></entry>
> +        </row>
> +        <row>
> +         <entry> <literal>+</literal> </entry>
> +         <entry>addition</entry>
> +         <entry><literal>inet '192.168.1.6' + 25</literal></entry>
> +        </row>
> +        <row>
> +         <entry> <literal>-</literal> </entry>
> +         <entry>subtraction</entry>
> +         <entry><literal>inet '192.168.1.43' - 36</literal></entry>
> +        </row>
> +        <row>
> +         <entry> <literal>-</literal> </entry>
> +         <entry>subtraction</entry>
> +         <entry><literal>inet '192.168.1.43' - inet '192.168.1.19'</literal></entry>
> +        </row>
>         </tbody>
>        </tgroup>
>       </table>
> Index: src/backend/utils/adt/network.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/backend/utils/adt/network.c,v
> retrieving revision 1.63
> diff -c -c -r1.63 network.c
> *** src/backend/utils/adt/network.c    7 Feb 2006 17:04:04 -0000    1.63
> --- src/backend/utils/adt/network.c    10 Feb 2006 04:11:57 -0000
> ***************
> *** 27,32 ****
> --- 27,33 ----
>   static int    bitncmp(void *l, void *r, int n);
>   static bool addressOK(unsigned char *a, int bits, int family);
>   static int    ip_addrsize(inet *inetptr);
> + static Datum internal_inetpl(inet *ip, int64 iarg);
>
>   /*
>    *    Access macros.
> ***************
> *** 1250,1252 ****
> --- 1251,1458 ----
>
>       PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
>   }
> +
> +
> + Datum
> + inetnot(PG_FUNCTION_ARGS)
> + {
> +     inet       *ip = PG_GETARG_INET_P(0);
> +     inet       *dst;
> +
> +     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
> +
> +     {
> +         int nb = ip_addrsize(ip);
> +         unsigned char    *pip = ip_addr(ip);
> +         unsigned char    *pdst = ip_addr(dst);
> +
> +         while (nb-- > 0)
> +             pdst[nb] = ~pip[nb];
> +     }
> +     ip_bits(dst) = ip_bits(ip);
> +
> +     ip_family(dst) = ip_family(ip);
> +     VARATT_SIZEP(dst) = VARHDRSZ +
> +         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
> +         ip_addrsize(dst);
> +
> +     PG_RETURN_INET_P(dst);
> + }
> +
> +
> + Datum
> + inetand(PG_FUNCTION_ARGS)
> + {
> +     inet       *ip = PG_GETARG_INET_P(0);
> +     inet       *ip2 = PG_GETARG_INET_P(1);
> +     inet       *dst;
> +
> +     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
> +
> +     if (ip_family(ip) != ip_family(ip2))
> +         ereport(ERROR,
> +                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> +                  errmsg("mismatch in address family (%d) != (%d)",
> +                         ip_family(ip), ip_family(ip2))));
> +     else
> +     {
> +         int nb = ip_addrsize(ip);
> +         unsigned char    *pip = ip_addr(ip);
> +         unsigned char    *pip2 = ip_addr(ip2);
> +         unsigned char    *pdst = ip_addr(dst);
> +
> +         while (nb-- > 0)
> +             pdst[nb] = pip[nb] & pip2[nb];
> +     }
> +     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
> +
> +     ip_family(dst) = ip_family(ip);
> +     VARATT_SIZEP(dst) = VARHDRSZ +
> +         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
> +         ip_addrsize(dst);
> +
> +     PG_RETURN_INET_P(dst);
> + }
> +
> +
> + Datum
> + inetor(PG_FUNCTION_ARGS)
> + {
> +     inet       *ip = PG_GETARG_INET_P(0);
> +     inet       *ip2 = PG_GETARG_INET_P(1);
> +     inet       *dst;
> +
> +     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
> +
> +     if (ip_family(ip) != ip_family(ip2))
> +         ereport(ERROR,
> +                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> +                  errmsg("mismatch in address family (%d) != (%d)",
> +                         ip_family(ip), ip_family(ip2))));
> +     else
> +     {
> +         int nb = ip_addrsize(ip);
> +         unsigned char    *pip = ip_addr(ip);
> +         unsigned char    *pip2 = ip_addr(ip2);
> +         unsigned char    *pdst = ip_addr(dst);
> +
> +         while (nb-- > 0)
> +             pdst[nb] = pip[nb] | pip2[nb];
> +     }
> +     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
> +
> +     ip_family(dst) = ip_family(ip);
> +     VARATT_SIZEP(dst) = VARHDRSZ +
> +         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
> +         ip_addrsize(dst);
> +
> +     PG_RETURN_INET_P(dst);
> + }
> +
> +
> + static Datum
> + internal_inetpl(inet *ip, int64 plus)
> + {
> +     inet       *dst;
> +
> +     dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
> +
> +     {
> +         int nb = ip_addrsize(ip);
> +         unsigned char    *pip = ip_addr(ip);
> +         unsigned char    *pdst = ip_addr(dst);
> +         int carry = 0;
> +
> +         while (nb-- > 0)
> +         {
> +             pdst[nb] = carry = pip[nb] + plus + carry;
> +             plus /= 0x100;        /* process next byte */
> +             carry /= 0x100;        /* remove low byte */
> +             /* Overflow on high byte? */
> +             if (nb == 0 && (plus != 0 || carry != 0))
> +                 ereport(ERROR,
> +                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
> +                          errmsg("result out of range")));
> +         }
> +     }
> +     ip_bits(dst) = ip_bits(ip);
> +
> +     ip_family(dst) = ip_family(ip);
> +     VARATT_SIZEP(dst) = VARHDRSZ +
> +         ((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
> +         ip_addrsize(dst);
> +
> +     PG_RETURN_INET_P(dst);
> + }
> +
> +
> + Datum
> + inetpl(PG_FUNCTION_ARGS)
> + {
> +     inet   *ip = PG_GETARG_INET_P(0);
> +     int64    plus = PG_GETARG_INT64(1);
> +
> +     return internal_inetpl(ip, plus);
> + }
> +
> +
> + Datum
> + inetmi_int8(PG_FUNCTION_ARGS)
> + {
> +     inet   *ip = PG_GETARG_INET_P(0);
> +     int64    plus = PG_GETARG_INT64(1);
> +
> +     return internal_inetpl(ip, -plus);
> + }
> +
> +
> + Datum
> + inetmi(PG_FUNCTION_ARGS)
> + {
> +     inet       *ip = PG_GETARG_INET_P(0);
> +     inet       *ip2 = PG_GETARG_INET_P(1);
> +     int64        res = 0;
> +
> +     if (ip_family(ip) != ip_family(ip2))
> +         ereport(ERROR,
> +                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> +                  errmsg("mismatch in address family (%d) != (%d)",
> +                         ip_family(ip), ip_family(ip2))));
> +     else
> +     {
> +         int nb = ip_addrsize(ip);
> +         int    byte = 0;
> +         unsigned char    *pip = ip_addr(ip);
> +         unsigned char    *pip2 = ip_addr(ip2);
> +
> +         while (nb-- > 0)
> +         {
> +             /*
> +              *    Error if overflow on last byte.  This test is tricky
> +              *    because if the subtraction == 128 and res is negative, or
> +              *    if subtraction == -128 and res is positive, the result
> +              *    would still fit in int64.
> +              */
> +             if (byte + 1 == sizeof(int64) &&
> +                 (pip[nb] - pip2[nb] >= 128 + (res < 0) ||
> +                  pip[nb] - pip2[nb] <= -128 - (res > 0)))
> +                 ereport(ERROR,
> +                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
> +                          errmsg("result out of range")));
> +             if (byte >= sizeof(int64))
> +             {
> +                 /* Error if bytes beyond int64 length differ. */
> +                 if (pip[nb] != pip2[nb])
> +                     ereport(ERROR,
> +                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
> +                              errmsg("result out of range")));
> +             }
> +             else
> +                 res += (int64)(pip[nb] - pip2[nb]) << (byte * 8);
> +
> +             byte++;
> +         }
> +     }
> +
> +     PG_RETURN_INT64(res);
> + }
> Index: src/include/catalog/pg_operator.h
> ===================================================================
> RCS file: /cvsroot/pgsql/src/include/catalog/pg_operator.h,v
> retrieving revision 1.138
> diff -c -c -r1.138 pg_operator.h
> *** src/include/catalog/pg_operator.h    26 Jan 2006 02:35:49 -0000    1.138
> --- src/include/catalog/pg_operator.h    10 Feb 2006 04:11:59 -0000
> ***************
> *** 653,658 ****
> --- 653,667 ----
>   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
>
> + DATA(insert OID = 2634 (  "~"       PGNSP PGUID l f    0 869 869 0 0 0 0 0 0 inetnot - - ));
> + DATA(insert OID = 2635 (  "&"       PGNSP PGUID b f    869 869 869 0 0 0 0 0 0 inetand - - ));
> + DATA(insert OID = 2636 (  "|"       PGNSP PGUID b f    869 869 869 0 0 0 0 0 0 inetor - - ));
> + DATA(insert OID = 2637 (  "+"       PGNSP PGUID b f    869 20 869 2638 0 0 0 0 0 inetpl - - ));
> + DATA(insert OID = 2638 (  "+"       PGNSP PGUID b f    20 869 869 2637 0 0 0 0 0 int8pl_inet - - ));
> + DATA(insert OID = 2639 (  "-"       PGNSP PGUID b f    869 20 869 0 0 0 0 0 0 inetmi_int8 - - ));
> + DATA(insert OID = 2640 (  "-"       PGNSP PGUID b f    869 869 20 0 0 0 0 0 0 inetmi - - ));
> +
> +
>   /* 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: src/include/catalog/pg_proc.h
> ===================================================================
> RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v
> retrieving revision 1.394
> diff -c -c -r1.394 pg_proc.h
> *** src/include/catalog/pg_proc.h    9 Feb 2006 14:53:51 -0000    1.394
> --- src/include/catalog/pg_proc.h    10 Feb 2006 04:12:03 -0000
> ***************
> *** 2431,2436 ****
> --- 2431,2451 ----
>   DATA(insert OID = 2199 (  inet_server_port        PGNSP PGUID 12 f f f f s 0 23 "" _null_ _null_ _null_
inet_server_port- _null_ )); 
>   DESCR("server's port number for this connection");
>
> + DATA(insert OID = 2627 (  inetnot            PGNSP PGUID 12 f f t f i 1 869 "869" _null_ _null_ _null_    inetnot -
_null_)); 
> + DESCR("binary NOT");
> + DATA(insert OID = 2628 (  inetand            PGNSP PGUID 12 f f t f i 2 869 "869 869" _null_ _null_ _null_
inetand- _null_ )); 
> + DESCR("binary AND");
> + DATA(insert OID = 2629 (  inetor            PGNSP PGUID 12 f f t f i 2 869 "869 869" _null_ _null_ _null_    inetor
-_null_ )); 
> + DESCR("binary OR");
> + DATA(insert OID = 2630 (  inetpl            PGNSP PGUID 12 f f t f i 2 869 "869 20" _null_ _null_ _null_    inetpl
-_null_ )); 
> + DESCR("add integer to INET value");
> + DATA(insert OID = 2631 ( int8pl_inet        PGNSP PGUID 14 f f t f i 2 869 "20 869" _null_ _null_ _null_    "select
$2+ $1" - _null_ )); 
> + DESCR("add integer to INET value");
> + DATA(insert OID = 2632 (  inetmi_int8        PGNSP PGUID 12 f f t f i 2 869 "869 20" _null_ _null_ _null_
inetmi_int8- _null_ )); 
> + DESCR("subtract integer from INET value");
> + DATA(insert OID = 2633 (  inetmi            PGNSP PGUID 12 f f t f i 2 20 "869 869" _null_ _null_ _null_    inetmi
-_null_ )); 
> + DESCR("subtract INET values");
> +
>   DATA(insert OID = 1686 ( numeric            PGNSP PGUID 12 f f t f i 1 1700 "25" _null_ _null_ _null_ text_numeric
-_null_ )); 
>   DESCR("(internal)");
>   DATA(insert OID = 1688 ( text                PGNSP PGUID 12 f f t f i 1 25 "1700" _null_ _null_ _null_ numeric_text
-_null_ )); 
> Index: src/include/utils/builtins.h
> ===================================================================
> RCS file: /cvsroot/pgsql/src/include/utils/builtins.h,v
> retrieving revision 1.272
> diff -c -c -r1.272 builtins.h
> *** src/include/utils/builtins.h    26 Jan 2006 02:35:50 -0000    1.272
> --- src/include/utils/builtins.h    10 Feb 2006 04:12:04 -0000
> ***************
> *** 734,739 ****
> --- 734,745 ----
>   extern Datum inet_client_port(PG_FUNCTION_ARGS);
>   extern Datum inet_server_addr(PG_FUNCTION_ARGS);
>   extern Datum inet_server_port(PG_FUNCTION_ARGS);
> + extern Datum inetnot(PG_FUNCTION_ARGS);
> + extern Datum inetand(PG_FUNCTION_ARGS);
> + extern Datum inetor(PG_FUNCTION_ARGS);
> + extern Datum inetpl(PG_FUNCTION_ARGS);
> + extern Datum inetmi_int8(PG_FUNCTION_ARGS);
> + extern Datum inetmi(PG_FUNCTION_ARGS);
>
>   /* mac.c */
>   extern Datum macaddr_in(PG_FUNCTION_ARGS);
> Index: src/test/regress/expected/inet.out
> ===================================================================
> RCS file: /cvsroot/pgsql/src/test/regress/expected/inet.out,v
> retrieving revision 1.19
> diff -c -c -r1.19 inet.out
> *** src/test/regress/expected/inet.out    8 Oct 2004 01:45:37 -0000    1.19
> --- src/test/regress/expected/inet.out    10 Feb 2006 04:12:05 -0000
> ***************
> *** 240,244 ****
> --- 240,376 ----
>    192.168.1.0/26 | 192.168.1.226
>   (6 rows)
>
> + SELECT ~i FROM inet_tbl;
> +                   ?column?
> + --------------------------------------------
> +  63.87.254.29/24
> +  63.87.254.29
> +  63.87.254.255/24
> +  63.87.254.255/25
> +  63.87.254.0/24
> +  63.87.254.0/25
> +  245.254.253.252/8
> +  245.254.253.252/8
> +  245.254.253.252
> +  245.254.253.252/24
> +  245.254.253.252/16
> +  245.254.253.252/8
> +  244.254.253.252/8
> +  246.254.253.252/8
> +  ffef:ffdc:ffff:ffff:ffff:ffff:ffff:ff0e/64
> +  ffef:ffdc:ffff:ffff:ffff:ffff:ffff:0
> +  ffff:ffff:ffff:ffff:ffff:ffff:fbfc:fdfe/24
> + (17 rows)
> +
> + SELECT i & c FROM inet_tbl;
> +     ?column?
> + ----------------
> +  192.168.1.0/24
> +  192.168.1.0
> +  192.168.1.0/24
> +  192.168.1.0/25
> +  192.168.1.0/24
> +  192.168.1.0/25
> +  10.0.0.0/8
> +  10.0.0.0
> +  10.1.2.3
> +  10.1.2.0/24
> +  10.1.0.0/16
> +  10.0.0.0/8
> +  10.0.0.0/8
> +  8.0.0.0/8
> +  10:23::f1
> +  10:23::8000
> +  ::0.2.2.0
> + (17 rows)
> +
> + SELECT i | c FROM inet_tbl;
> +      ?column?
> + ------------------
> +  192.168.1.226/24
> +  192.168.1.226
> +  192.168.1.0/24
> +  192.168.1.0/25
> +  192.168.1.255/24
> +  192.168.1.255/25
> +  10.1.2.3/8
> +  10.1.2.3
> +  10.1.2.3
> +  10.1.2.3/24
> +  10.1.2.3/16
> +  10.1.2.3/8
> +  11.1.2.3/8
> +  11.1.2.3/8
> +  10:23::f1
> +  10:23::ffff
> +  ::ffff:5.3.3.5
> + (17 rows)
> +
> + SELECT i + 500 FROM inet_tbl;
> +      ?column?
> + ------------------
> +  192.168.4.214/24
> +  192.168.4.214
> +  192.168.3.244/24
> +  192.168.3.244/25
> +  192.168.4.243/24
> +  192.168.4.243/25
> +  10.1.4.247/8
> +  10.1.4.247/8
> +  10.1.4.247
> +  10.1.4.247/24
> +  10.1.4.247/16
> +  10.1.4.247/8
> +  11.1.4.247/8
> +  9.1.4.247/8
> +  10:23::3e5/64
> +  10:23::1:2f3
> +  ::4.3.4.245/24
> + (17 rows)
> +
> + SELECT i - 500 FROM inet_tbl;
> +                 ?column?
> + --------------------
> +  192.168.255.238/24
> +  192.168.255.238
> +  192.168.255.12/24
> +  192.168.255.12/25
> +  192.168.0.11/24
> +  192.168.0.11/25
> +  10.1.0.15/8
> +  10.1.0.15/8
> +  10.1.0.15
> +  10.1.0.15/24
> +  10.1.0.15/16
> +  10.1.0.15/8
> +  11.1.0.15/8
> +  9.1.0.15/8
> +  10:23::fefd/64
> +  10:23::fe0b
> +  ::4.3.0.13/24
> + (17 rows)
> +
> + SELECT i - c FROM inet_tbl;
> +  ?column?
> + ------------------
> +        226
> +        226
> +          0
> +          0
> +        255
> +        255
> +      66051
> +      66051
> +          0
> +          3
> +        515
> +      66051
> +   16843267
> +  -16711165
> +                 0
> +             32767
> +  -281470631346435
> + (17 rows)
> +
>   SET enable_seqscan TO on;
>   DROP INDEX inet_idx1;
> Index: src/test/regress/sql/inet.sql
> ===================================================================
> RCS file: /cvsroot/pgsql/src/test/regress/sql/inet.sql,v
> retrieving revision 1.11
> diff -c -c -r1.11 inet.sql
> *** src/test/regress/sql/inet.sql    8 Oct 2004 01:45:37 -0000    1.11
> --- src/test/regress/sql/inet.sql    10 Feb 2006 04:12:05 -0000
> ***************
> *** 62,67 ****
> --- 62,75 ----
>   SET enable_seqscan TO off;
>   SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr;
>   SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
> +
> + SELECT ~i FROM inet_tbl;
> + SELECT i & c FROM inet_tbl;
> + SELECT i | c FROM inet_tbl;
> + SELECT i + 500 FROM inet_tbl;
> + SELECT i - 500 FROM inet_tbl;
> + SELECT i - c FROM inet_tbl;
> +
>   SET enable_seqscan TO on;
>   DROP INDEX inet_idx1;
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Have you searched our list archives?
>
>                http://archives.postgresql.org

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073