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: