inet increment w/ int8 - Mailing list pgsql-hackers
| From | Ilya A. Kovalenko |
|---|---|
| Subject | inet increment w/ int8 |
| Date | |
| Msg-id | 17534258300.20050418042534@oganer.net Whole thread Raw |
| Responses |
Re: inet increment w/ int8
Re: inet increment w/ int8 |
| List | pgsql-hackers |
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:shadow@oganer.net)
SpecialEQ SW section
JSC Oganer-Service
P.S. Treat as Public Domain
pgsql-hackers by date: