Greetings,

  I suggest function for "inet" increment w/ int8 (signed).

FUNCTION inet_inc(int, int8) RETURNS inet

Function, useful for making address pools (using also
existing "inet" compare functions to trap boundaries).

Notes:
  This version lets address wrap around 0-*ff boundary.
  Uses couple of non-POSIX functions - betoh64() and htobe64()
  Tested on i386 with OpenBSD 3.7
  PostgreSQL 8.0.2

-----------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "postgres.h"                   /* general Postgres declarations */

#include "fmgr.h"                       /* for argument/result macros */
#include "utils/inet.h"

Datum           inet_inc(PG_FUNCTION_ARGS);

//------ stolen from backend/utils/adt/network.c --------

#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)
#define ip_maxbits(inetptr) \
        (ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)

static int
ip_addrsize(inet *inetptr)
{
        switch (ip_family(inetptr))
        {
                case PGSQL_AF_INET:
                        return 4;
                case PGSQL_AF_INET6:
                        return 16;
                default:
                        return 0;
        }
}
//-------------------------------------------------------

PG_FUNCTION_INFO_V1(inet_inc);

Datum
inet_inc(PG_FUNCTION_ARGS)
{
   inet    *src = PG_GETARG_INET_P(0);
   int64    arg = PG_GETARG_INT64(1);
   inet    *dst;
   uint64   wsp;

// allocate destination structure
   dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));

// copy to destination
   *((inet_struct *)VARDATA(dst)) = *((inet_struct *)VARDATA(src));

   if (ip_family(dst) == PGSQL_AF_INET)
   {
// Increment v4 address w/ item truncated to 32 bits
      *((uint32*)(ip_addr(dst))) =
          htonl(ntohl(*((int32*)(ip_addr(dst)))) + (int32)arg);
   }
   else
   {
// Increment v6 address low qword (store to workspace)
      wsp = htobe64(betoh64(*((int64*)(ip_addr(dst) + 8))) + arg);
      *((uint64*)(ip_addr(dst) + 8)) = wsp;

// Carry/borrow high qword
      if ( arg > 0 && wsp < *((uint64*)(ip_addr(src) + 8)) )
      {  *((int64*)(ip_addr(dst))) =
             htobe64(betoh64(*((int64*)(ip_addr(dst)))) + 1);
      }
      else
         if ( arg < 0 && wsp > *((uint64*)(ip_addr(src) + 8)) )
         {  *((int64*)(ip_addr(dst))) =
                htobe64(betoh64(*((int64*)(ip_addr(dst)))) - 1);
         }
   }

// Return result
   VARATT_SIZEP(dst) = VARHDRSZ
          + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
          + ip_addrsize(dst);

   PG_RETURN_INET_P(dst);

}
-----------------------------------------------------

Thank you

Ilya A. Kovalenko         (mailto:[EMAIL PROTECTED])
SpecialEQ SW section
JSC Oganer-Service

P.S. Treat as Public Domain


---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Reply via email to