Skip to content

Commit 1372515

Browse files
committed
Add INET/CIDR operators: and, or, not, plus int8, minus int8, and inet
minus inet. Stephen R. van den Berg
1 parent 9bf2ac2 commit 1372515

File tree

7 files changed

+411
-5
lines changed

7 files changed

+411
-5
lines changed

doc/src/sgml/func.sgml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.303 2006/01/26 02:35:48 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.304 2006/02/11 03:32:38 momjian Exp $
33
PostgreSQL documentation
44
-->
55

@@ -6787,6 +6787,36 @@ SELECT pg_sleep(1.5);
67876787
<entry>contains or equals</entry>
67886788
<entry><literal>inet '192.168.1/24' &gt;&gt;= inet '192.168.1/24'</literal></entry>
67896789
</row>
6790+
<row>
6791+
<entry> <literal>~</literal> </entry>
6792+
<entry>bitwise NOT</entry>
6793+
<entry><literal>~ inet '192.168.1.6'</literal></entry>
6794+
</row>
6795+
<row>
6796+
<entry> <literal>&amp;</literal> </entry>
6797+
<entry>bitwise AND</entry>
6798+
<entry><literal>inet '192.168.1.6' &amp; inet '0.0.0.255'</literal></entry>
6799+
</row>
6800+
<row>
6801+
<entry> <literal>|</literal> </entry>
6802+
<entry>bitwise OR</entry>
6803+
<entry><literal>inet '192.168.1.6' | inet '0.0.0.255'</literal></entry>
6804+
</row>
6805+
<row>
6806+
<entry> <literal>+</literal> </entry>
6807+
<entry>addition</entry>
6808+
<entry><literal>inet '192.168.1.6' + 25</literal></entry>
6809+
</row>
6810+
<row>
6811+
<entry> <literal>-</literal> </entry>
6812+
<entry>subtraction</entry>
6813+
<entry><literal>inet '192.168.1.43' - 36</literal></entry>
6814+
</row>
6815+
<row>
6816+
<entry> <literal>-</literal> </entry>
6817+
<entry>subtraction</entry>
6818+
<entry><literal>inet '192.168.1.43' - inet '192.168.1.19'</literal></entry>
6819+
</row>
67906820
</tbody>
67916821
</tgroup>
67926822
</table>

src/backend/utils/adt/network.c

Lines changed: 207 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* PostgreSQL type definitions for the INET and CIDR types.
33
*
4-
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.63 2006/02/07 17:04:04 momjian Exp $
4+
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.64 2006/02/11 03:32:39 momjian Exp $
55
*
66
* Jon Postel RIP 16 Oct 1998
77
*/
@@ -27,6 +27,7 @@ static int32 network_cmp_internal(inet *a1, inet *a2);
2727
static int bitncmp(void *l, void *r, int n);
2828
static bool addressOK(unsigned char *a, int bits, int family);
2929
static int ip_addrsize(inet *inetptr);
30+
static Datum internal_inetpl(inet *ip, int64 iarg);
3031

3132
/*
3233
* Access macros.
@@ -1250,3 +1251,208 @@ inet_server_port(PG_FUNCTION_ARGS)
12501251

12511252
PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
12521253
}
1254+
1255+
1256+
Datum
1257+
inetnot(PG_FUNCTION_ARGS)
1258+
{
1259+
inet *ip = PG_GETARG_INET_P(0);
1260+
inet *dst;
1261+
1262+
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
1263+
1264+
{
1265+
int nb = ip_addrsize(ip);
1266+
unsigned char *pip = ip_addr(ip);
1267+
unsigned char *pdst = ip_addr(dst);
1268+
1269+
while (nb-- > 0)
1270+
pdst[nb] = ~pip[nb];
1271+
}
1272+
ip_bits(dst) = ip_bits(ip);
1273+
1274+
ip_family(dst) = ip_family(ip);
1275+
VARATT_SIZEP(dst) = VARHDRSZ +
1276+
((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
1277+
ip_addrsize(dst);
1278+
1279+
PG_RETURN_INET_P(dst);
1280+
}
1281+
1282+
1283+
Datum
1284+
inetand(PG_FUNCTION_ARGS)
1285+
{
1286+
inet *ip = PG_GETARG_INET_P(0);
1287+
inet *ip2 = PG_GETARG_INET_P(1);
1288+
inet *dst;
1289+
1290+
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
1291+
1292+
if (ip_family(ip) != ip_family(ip2))
1293+
ereport(ERROR,
1294+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1295+
errmsg("mismatch in address family (%d) != (%d)",
1296+
ip_family(ip), ip_family(ip2))));
1297+
else
1298+
{
1299+
int nb = ip_addrsize(ip);
1300+
unsigned char *pip = ip_addr(ip);
1301+
unsigned char *pip2 = ip_addr(ip2);
1302+
unsigned char *pdst = ip_addr(dst);
1303+
1304+
while (nb-- > 0)
1305+
pdst[nb] = pip[nb] & pip2[nb];
1306+
}
1307+
ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
1308+
1309+
ip_family(dst) = ip_family(ip);
1310+
VARATT_SIZEP(dst) = VARHDRSZ +
1311+
((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
1312+
ip_addrsize(dst);
1313+
1314+
PG_RETURN_INET_P(dst);
1315+
}
1316+
1317+
1318+
Datum
1319+
inetor(PG_FUNCTION_ARGS)
1320+
{
1321+
inet *ip = PG_GETARG_INET_P(0);
1322+
inet *ip2 = PG_GETARG_INET_P(1);
1323+
inet *dst;
1324+
1325+
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
1326+
1327+
if (ip_family(ip) != ip_family(ip2))
1328+
ereport(ERROR,
1329+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1330+
errmsg("mismatch in address family (%d) != (%d)",
1331+
ip_family(ip), ip_family(ip2))));
1332+
else
1333+
{
1334+
int nb = ip_addrsize(ip);
1335+
unsigned char *pip = ip_addr(ip);
1336+
unsigned char *pip2 = ip_addr(ip2);
1337+
unsigned char *pdst = ip_addr(dst);
1338+
1339+
while (nb-- > 0)
1340+
pdst[nb] = pip[nb] | pip2[nb];
1341+
}
1342+
ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
1343+
1344+
ip_family(dst) = ip_family(ip);
1345+
VARATT_SIZEP(dst) = VARHDRSZ +
1346+
((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
1347+
ip_addrsize(dst);
1348+
1349+
PG_RETURN_INET_P(dst);
1350+
}
1351+
1352+
1353+
static Datum
1354+
internal_inetpl(inet *ip, int64 plus)
1355+
{
1356+
inet *dst;
1357+
1358+
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
1359+
1360+
{
1361+
int nb = ip_addrsize(ip);
1362+
unsigned char *pip = ip_addr(ip);
1363+
unsigned char *pdst = ip_addr(dst);
1364+
int carry = 0;
1365+
1366+
while (nb-- > 0)
1367+
{
1368+
pdst[nb] = carry = pip[nb] + plus + carry;
1369+
plus /= 0x100; /* process next byte */
1370+
carry /= 0x100; /* remove low byte */
1371+
/* Overflow on high byte? */
1372+
if (nb == 0 && (plus != 0 || carry != 0))
1373+
ereport(ERROR,
1374+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1375+
errmsg("result out of range")));
1376+
}
1377+
}
1378+
ip_bits(dst) = ip_bits(ip);
1379+
1380+
ip_family(dst) = ip_family(ip);
1381+
VARATT_SIZEP(dst) = VARHDRSZ +
1382+
((char *) ip_addr(dst) - (char *) VARDATA(dst)) +
1383+
ip_addrsize(dst);
1384+
1385+
PG_RETURN_INET_P(dst);
1386+
}
1387+
1388+
1389+
Datum
1390+
inetpl(PG_FUNCTION_ARGS)
1391+
{
1392+
inet *ip = PG_GETARG_INET_P(0);
1393+
int64 plus = PG_GETARG_INT64(1);
1394+
1395+
return internal_inetpl(ip, plus);
1396+
}
1397+
1398+
1399+
Datum
1400+
inetmi_int8(PG_FUNCTION_ARGS)
1401+
{
1402+
inet *ip = PG_GETARG_INET_P(0);
1403+
int64 plus = PG_GETARG_INT64(1);
1404+
1405+
return internal_inetpl(ip, -plus);
1406+
}
1407+
1408+
1409+
Datum
1410+
inetmi(PG_FUNCTION_ARGS)
1411+
{
1412+
inet *ip = PG_GETARG_INET_P(0);
1413+
inet *ip2 = PG_GETARG_INET_P(1);
1414+
int64 res = 0;
1415+
1416+
if (ip_family(ip) != ip_family(ip2))
1417+
ereport(ERROR,
1418+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1419+
errmsg("mismatch in address family (%d) != (%d)",
1420+
ip_family(ip), ip_family(ip2))));
1421+
else
1422+
{
1423+
int nb = ip_addrsize(ip);
1424+
int byte = 0;
1425+
unsigned char *pip = ip_addr(ip);
1426+
unsigned char *pip2 = ip_addr(ip2);
1427+
1428+
while (nb-- > 0)
1429+
{
1430+
/*
1431+
* Error if overflow on last byte. This test is tricky
1432+
* because if the subtraction == 128 and res is negative, or
1433+
* if subtraction == -128 and res is positive, the result
1434+
* would still fit in int64.
1435+
*/
1436+
if (byte + 1 == sizeof(int64) &&
1437+
(pip[nb] - pip2[nb] >= 128 + (res < 0) ||
1438+
pip[nb] - pip2[nb] <= -128 - (res > 0)))
1439+
ereport(ERROR,
1440+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1441+
errmsg("result out of range")));
1442+
if (byte >= sizeof(int64))
1443+
{
1444+
/* Error if bytes beyond int64 length differ. */
1445+
if (pip[nb] != pip2[nb])
1446+
ereport(ERROR,
1447+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1448+
errmsg("result out of range")));
1449+
}
1450+
else
1451+
res += (int64)(pip[nb] - pip2[nb]) << (byte * 8);
1452+
1453+
byte++;
1454+
}
1455+
}
1456+
1457+
PG_RETURN_INT64(res);
1458+
}

src/include/catalog/pg_operator.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.138 2006/01/26 02:35:49 tgl Exp $
11+
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.139 2006/02/11 03:32:39 momjian Exp $
1212
*
1313
* NOTES
1414
* 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
653653
DATA(insert OID = 934 ( ">>=" PGNSP PGUID b f 869 869 16 932 0 0 0 0 0 network_supeq - - ));
654654
#define OID_INET_SUPEQ_OP 934
655655

656+
DATA(insert OID = 2634 ( "~" PGNSP PGUID l f 0 869 869 0 0 0 0 0 0 inetnot - - ));
657+
DATA(insert OID = 2635 ( "&" PGNSP PGUID b f 869 869 869 0 0 0 0 0 0 inetand - - ));
658+
DATA(insert OID = 2636 ( "|" PGNSP PGUID b f 869 869 869 0 0 0 0 0 0 inetor - - ));
659+
DATA(insert OID = 2637 ( "+" PGNSP PGUID b f 869 20 869 2638 0 0 0 0 0 inetpl - - ));
660+
DATA(insert OID = 2638 ( "+" PGNSP PGUID b f 20 869 869 2637 0 0 0 0 0 int8pl_inet - - ));
661+
DATA(insert OID = 2639 ( "-" PGNSP PGUID b f 869 20 869 0 0 0 0 0 0 inetmi_int8 - - ));
662+
DATA(insert OID = 2640 ( "-" PGNSP PGUID b f 869 869 20 0 0 0 0 0 0 inetmi - - ));
663+
664+
656665
/* case-insensitive LIKE hacks */
657666
DATA(insert OID = 1625 ( "~~*" PGNSP PGUID b f 19 25 16 0 1626 0 0 0 0 nameiclike iclikesel iclikejoinsel ));
658667
#define OID_NAME_ICLIKE_OP 1625

src/include/catalog/pg_proc.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.394 2006/02/09 14:53:51 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.395 2006/02/11 03:32:39 momjian Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2431,6 +2431,21 @@ DESCR("INET address of the server");
24312431
DATA(insert OID = 2199 ( inet_server_port PGNSP PGUID 12 f f f f s 0 23 "" _null_ _null_ _null_ inet_server_port - _null_ ));
24322432
DESCR("server's port number for this connection");
24332433

2434+
DATA(insert OID = 2627 ( inetnot PGNSP PGUID 12 f f t f i 1 869 "869" _null_ _null_ _null_ inetnot - _null_ ));
2435+
DESCR("binary NOT");
2436+
DATA(insert OID = 2628 ( inetand PGNSP PGUID 12 f f t f i 2 869 "869 869" _null_ _null_ _null_ inetand - _null_ ));
2437+
DESCR("binary AND");
2438+
DATA(insert OID = 2629 ( inetor PGNSP PGUID 12 f f t f i 2 869 "869 869" _null_ _null_ _null_ inetor - _null_ ));
2439+
DESCR("binary OR");
2440+
DATA(insert OID = 2630 ( inetpl PGNSP PGUID 12 f f t f i 2 869 "869 20" _null_ _null_ _null_ inetpl - _null_ ));
2441+
DESCR("add integer to INET value");
2442+
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_ ));
2443+
DESCR("add integer to INET value");
2444+
DATA(insert OID = 2632 ( inetmi_int8 PGNSP PGUID 12 f f t f i 2 869 "869 20" _null_ _null_ _null_ inetmi_int8 - _null_ ));
2445+
DESCR("subtract integer from INET value");
2446+
DATA(insert OID = 2633 ( inetmi PGNSP PGUID 12 f f t f i 2 20 "869 869" _null_ _null_ _null_ inetmi - _null_ ));
2447+
DESCR("subtract INET values");
2448+
24342449
DATA(insert OID = 1686 ( numeric PGNSP PGUID 12 f f t f i 1 1700 "25" _null_ _null_ _null_ text_numeric - _null_ ));
24352450
DESCR("(internal)");
24362451
DATA(insert OID = 1688 ( text PGNSP PGUID 12 f f t f i 1 25 "1700" _null_ _null_ _null_ numeric_text - _null_ ));

src/include/utils/builtins.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.272 2006/01/26 02:35:50 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.273 2006/02/11 03:32:41 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -734,6 +734,12 @@ extern Datum inet_client_addr(PG_FUNCTION_ARGS);
734734
extern Datum inet_client_port(PG_FUNCTION_ARGS);
735735
extern Datum inet_server_addr(PG_FUNCTION_ARGS);
736736
extern Datum inet_server_port(PG_FUNCTION_ARGS);
737+
extern Datum inetnot(PG_FUNCTION_ARGS);
738+
extern Datum inetand(PG_FUNCTION_ARGS);
739+
extern Datum inetor(PG_FUNCTION_ARGS);
740+
extern Datum inetpl(PG_FUNCTION_ARGS);
741+
extern Datum inetmi_int8(PG_FUNCTION_ARGS);
742+
extern Datum inetmi(PG_FUNCTION_ARGS);
737743

738744
/* mac.c */
739745
extern Datum macaddr_in(PG_FUNCTION_ARGS);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy