Commit 13725152 authored by Bruce Momjian's avatar Bruce Momjian

Add INET/CIDR operators: and, or, not, plus int8, minus int8, and inet

minus inet.

Stephen R. van den Berg
parent 9bf2ac2a
<!--
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.303 2006/01/26 02:35:48 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.304 2006/02/11 03:32:38 momjian Exp $
PostgreSQL documentation
-->
......@@ -6787,6 +6787,36 @@ SELECT pg_sleep(1.5);
<entry>contains or equals</entry>
<entry><literal>inet '192.168.1/24' &gt;&gt;= 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>&amp;</literal> </entry>
<entry>bitwise AND</entry>
<entry><literal>inet '192.168.1.6' &amp; 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>
......
/*
* PostgreSQL type definitions for the INET and CIDR types.
*
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.63 2006/02/07 17:04:04 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.64 2006/02/11 03:32:39 momjian Exp $
*
* Jon Postel RIP 16 Oct 1998
*/
......@@ -27,6 +27,7 @@ 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);
static int ip_addrsize(inet *inetptr);
static Datum internal_inetpl(inet *ip, int64 iarg);
/*
* Access macros.
......@@ -1250,3 +1251,208 @@ inet_server_port(PG_FUNCTION_ARGS)
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);
}
......@@ -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.138 2006/01/26 02:35:49 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.139 2006/02/11 03:32:39 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -653,6 +653,15 @@ 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
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
......
......@@ -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.394 2006/02/09 14:53:51 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.395 2006/02/11 03:32:39 momjian Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -2431,6 +2431,21 @@ DESCR("INET address of the server");
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_ ));
......
......@@ -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.272 2006/01/26 02:35:50 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.273 2006/02/11 03:32:41 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -734,6 +734,12 @@ extern Datum inet_client_addr(PG_FUNCTION_ARGS);
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);
......
......@@ -240,5 +240,137 @@ SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
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;
......@@ -62,6 +62,14 @@ CREATE INDEX inet_idx1 ON inet_tbl(i);
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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment